这次考试T1想到了正解没有去实现,然后就死了,不过我估计就算想到正解也会挂(26^2和暴力一个分),肝了两个小时T2屁都没蹦出来,T3没有搞清那个式子的含义。
(不过一分没挂)
T1:string
开26棵线段树维护,还有一种更快的方法:对于每个树上的节点,只有左右儿子字符相同时才更新,不然不更新,这种打法将26换成了较小的常数,并且不需要memset,真是出家旅行必备骗分之良器

1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 5 inline int rd() { 6 int a = 1, b = 0; char c = getchar(); 7 while (!isdigit(c)) a = c == '-' ? 0 : 1, c = getchar(); 8 while (isdigit(c)) b = b * 10 + c - '0', c = getchar(); 9 return a ? b : -b; 10 } 11 12 const int N = 100000 + 2333; 13 14 int n, m; char str[N]; 15 16 int same[N * 3]; 17 18 #define ls(p) p << 1 19 #define rs(p) p << 1 | 1 20 21 void pushup(int p) { 22 if (same[ls(p)] == same[rs(p)]) 23 same[p] = same[ls(p)]; 24 else same[p] = 0; 25 } 26 27 void pushdown(int p) { 28 if (same[p]) 29 same[ls(p)] = same[rs(p)] = same[p]; 30 } 31 32 void build(int p, int L, int R) { 33 if (L == R) return (void)(same[p] = str[L]); 34 int mid = (L + R) >> 1; 35 build(ls(p), L, mid); 36 build(rs(p), mid + 1, R); 37 pushup(p); 38 } 39 40 void change(int p, int l, int r, int v, int L, int R) { 41 if (l <= L && r >= R) return (void)(same[p] = v); 42 pushdown(p); int mid = (L + R) >> 1; 43 if (l <= mid) change(ls(p), l, r, v, L, mid); 44 if (r > mid) change(rs(p), l, r, v, mid + 1, R); 45 pushup(p); 46 } 47 48 int que[233]; 49 50 void query(int p, int l, int r, int L, int R) { 51 if (l <= L && r >= R && same[p]) 52 return (void)(que[same[p]] += (R - L + 1)); 53 pushdown(p); int mid = (L + R) >> 1; 54 if (l <= mid) query(ls(p), l, r, L, mid); 55 if (r > mid) query(rs(p), l, r, mid + 1, R); 56 } 57 58 void write(int p, int L, int R) { 59 if (L == R) return (void)(putchar(same[p])); 60 pushdown(p); int mid = (L + R) >> 1; 61 write(ls(p), L, mid); 62 write(rs(p), mid + 1, R); 63 } 64 65 int main() { 66 scanf("%d%d%s", &n, &m, str + 1); 67 build(1, 1, n); 68 while (m--) { 69 int l, r, x; scanf("%d%d%d", &l, &r, &x); 70 for (int i = 'a'; i <= 'z'; ++i) que[i] = 0; 71 query(1, l, r, 1, n); 72 if (x == 1) { 73 for (int i = 'a', lst = l; i <= 'z'; ++i) if (que[i]) 74 change(1, lst, lst + que[i] - 1, i, 1, n), lst = lst + que[i]; 75 } else { 76 for (int i = 'z', lst = l; i >= 'a'; --i) if (que[i]) 77 change(1, lst, lst + que[i] - 1, i, 1, n), lst = lst + que[i]; 78 } 79 } 80 write(1, 1, n); 81 return 0; 82 }

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define clr(x) memset(x,0,sizeof(x)) 5 using namespace std; 6 const int MAXN=800100; 7 int N,M; 8 char s[MAXN]; 9 int t[30]; 10 char wd[MAXN*4]; 11 int cnt[MAXN*4][30],tg[MAXN]; 12 bool fg[MAXN*4]; 13 void bt(int p,int l,int r){ 14 tg[p]=-1; 15 if(l==r){ 16 wd[p]=s[l]; 17 cnt[p][s[l]-'a']=1; 18 return; 19 } 20 int mid=(l+r)>>1; 21 bt(p<<1,l,mid); 22 bt(p<<1|1,mid+1,r); 23 int fgg=0; 24 for(int i=0;i<26;++i){ 25 cnt[p][i]=cnt[p<<1][i]+cnt[p<<1|1][i]; 26 fgg+=(cnt[p][i]!=0); 27 } 28 fg[p]=(fgg==1); 29 } 30 void get(int p,int l,int r,int ll,int rr,int out[]){ 31 if(ll<=l && r<=rr){ 32 for(int i=0;i<26;++i) 33 out[i]+=cnt[p][i]; 34 return; 35 } 36 if(tg[p]!=-1){ 37 int id=tg[p]; 38 int mid=(l+r)>>1; 39 clr(cnt[p<<1]); 40 clr(cnt[p<<1|1]); 41 cnt[p<<1][id]=mid-l+1; 42 cnt[p<<1|1][id]=r-(mid+1)+1; 43 tg[p<<1]=tg[p<<1|1]=id; 44 wd[p<<1]=wd[p<<1|1]=id+'a'; 45 fg[p<<1]=fg[p<<1|1]=1; 46 tg[p]=-1; 47 } 48 int mid=(l+r)>>1; 49 if(ll<=mid) 50 get(p<<1,l,mid,ll,rr,out); 51 if(rr>mid) 52 get(p<<1|1,mid+1,r,ll,rr,out); 53 } 54 void cover(int p,int l,int r,int ll,int rr,int id){ 55 if(ll<=l && r<=rr){ 56 clr(cnt[p]); 57 cnt[p][id]=r-l+1; 58 tg[p]=id; 59 wd[p]=id+'a'; 60 fg[p]=1; 61 return; 62 } 63 if(tg[p]!=-1){ 64 int id=tg[p]; 65 int mid=(l+r)>>1; 66 clr(cnt[p<<1]); 67 clr(cnt[p<<1|1]); 68 cnt[p<<1][id]=mid-l+1; 69 cnt[p<<1|1][id]=r-(mid+1)+1; 70 tg[p<<1]=tg[p<<1|1]=id; 71 wd[p<<1]=wd[p<<1|1]=id+'a'; 72 fg[p<<1]=fg[p<<1|1]=1; 73 tg[p]=-1; 74 } 75 int mid=(l+r)>>1; 76 if(ll<=mid) 77 cover(p<<1,l,mid,ll,rr,id); 78 if(rr>mid) 79 cover(p<<1|1,mid+1,r,ll,rr,id); 80 int fgg=0; 81 for(int i=0;i<26;++i){ 82 cnt[p][i]=cnt[p<<1][i]+cnt[p<<1|1][i]; 83 fgg+=(cnt[p]!=0); 84 } 85 fg[p]=(fgg==1); 86 } 87 void dfs(int p,int l,int r){ 88 if(l==r){ 89 printf("%c",wd[p]); 90 return; 91 } 92 if(tg[p]!=-1){ 93 int id=tg[p]; 94 int mid=(l+r)>>1; 95 clr(cnt[p<<1]); 96 clr(cnt[p<<1|1]); 97 cnt[p<<1][id]=mid-l+1; 98 cnt[p<<1|1][id]=r-(mid+1)+1; 99 tg[p<<1]=tg[p<<1|1]=id; 100 wd[p<<1]=wd[p<<1|1]=id+'a'; 101 fg[p<<1]=fg[p<<1|1]=1; 102 tg[p]=-1; 103 } 104 int mid=(l+r)>>1; 105 dfs(p<<1,l,mid); 106 dfs(p<<1|1,mid+1,r); 107 } 108 int main(){ 109 scanf("%d%d",&N,&M); 110 char c=getchar(); 111 int len=0; 112 while(c<'a' || c>'z') 113 c=getchar(); 114 while(c<='z' && c>='a'){ 115 s[++len]=c; 116 c=getchar(); 117 } 118 bt(1,1,N); 119 for(int i=1;i<=M;++i){ 120 int l,r,opt; 121 scanf("%d%d%d",&l,&r,&opt); 122 clr(t); 123 get(1,1,N,l,r,t); 124 if(opt==0){ 125 for(int i=25;i>=0;--i){ 126 if(t[i]) 127 cover(1,1,N,l,l+t[i]-1,i); 128 l+=t[i]; 129 } 130 } 131 else{ 132 for(int i=0;i<26;++i){ 133 if(t[i]) 134 cover(1,1,N,l,l+t[i]-1,i); 135 l+=t[i]; 136 } 137 } 138 } 139 dfs(1,1,N); 140 }

1 #include<bits/stdc++.h> 2 #define MAXN 100005 3 #define cri const register int 4 #define pt puts("----------------") 5 using namespace std; 6 int now[27]; 7 char s[MAXN]; 8 struct Seg_tree{ 9 int t[MAXN*4][27],f[MAXN*4]; 10 #define ls k<<1 11 #define rs k<<1|1 12 void change(cri k,cri l,cri r,cri gl,cri gr,cri val) 13 { 14 if(l>=gl&&r<=gr) 15 { 16 memset(t[k],0,sizeof(t[k])); 17 t[k][val]=r-l+1; 18 f[k]=val; 19 return ; 20 } 21 register int mid=l+r>>1; 22 if(f[k]) 23 { 24 register int mid=l+r>>1; 25 memset(t[ls],0,sizeof(t[ls])); 26 memset(t[rs],0,sizeof(t[rs])); 27 register int p=f[k];f[k]=0; 28 t[ls][p]=mid-l+1; 29 t[rs][p]=r-mid; 30 f[ls]=f[rs]=p; 31 } 32 if(gl<=mid)change(ls,l,mid,gl,gr,val); 33 if(gr>mid)change(rs,mid+1,r,gl,gr,val); 34 t[k][1]=t[ls][1]+t[rs][1]; 35 t[k][2]=t[ls][2]+t[rs][2]; 36 t[k][3]=t[ls][3]+t[rs][3]; 37 t[k][4]=t[ls][4]+t[rs][4]; 38 t[k][5]=t[ls][5]+t[rs][5]; 39 t[k][6]=t[ls][6]+t[rs][6]; 40 t[k][7]=t[ls][7]+t[rs][7]; 41 t[k][8]=t[ls][8]+t[rs][8]; 42 t[k][9]=t[ls][9]+t[rs][9]; 43 t[k][10]=t[ls][10]+t[rs][10]; 44 t[k][11]=t[ls][11]+t[rs][11]; 45 t[k][12]=t[ls][12]+t[rs][12]; 46 t[k][13]=t[ls][13]+t[rs][13]; 47 t[k][14]=t[ls][14]+t[rs][14]; 48 t[k][15]=t[ls][15]+t[rs][15]; 49 t[k][16]=t[ls][16]+t[rs][16]; 50 t[k][17]=t[ls][17]+t[rs][17]; 51 t[k][18]=t[ls][18]+t[rs][18]; 52 t[k][19]=t[ls][19]+t[rs][19]; 53 t[k][20]=t[ls][20]+t[rs][20]; 54 t[k][21]=t[ls][21]+t[rs][21]; 55 t[k][22]=t[ls][22]+t[rs][22]; 56 t[k][23]=t[ls][23]+t[rs][23]; 57 t[k][24]=t[ls][24]+t[rs][24]; 58 t[k][25]=t[ls][25]+t[rs][25]; 59 t[k][26]=t[ls][26]+t[rs][26]; 60 } 61 void query(cri k,cri l,cri r,cri gl,cri gr) 62 { 63 if(l>=gl&&r<=gr) 64 { 65 for(register int i=1;i<=26;i++)now[i]+=t[k][i]; 66 return ; 67 } 68 register int mid=l+r>>1; 69 if(f[k]) 70 { 71 register int mid=l+r>>1; 72 memset(t[ls],0,sizeof(t[ls])); 73 memset(t[rs],0,sizeof(t[rs])); 74 register int p=f[k];f[k]=0; 75 t[ls][p]=mid-l+1; 76 t[rs][p]=r-mid; 77 f[ls]=f[rs]=p; 78 } 79 if(gl<=mid)query(ls,l,mid,gl,gr); 80 if(gr>mid)query(rs,mid+1,r,gl,gr); 81 return ; 82 } 83 void Build(cri k,cri l,cri r) 84 { 85 if(l==r) 86 { 87 t[k][s[l-1]-'a'+1]=1; 88 return ; 89 } 90 register int mid=l+r>>1; 91 Build(ls,l,mid); 92 Build(rs,mid+1,r); 93 t[k][1]=t[ls][1]+t[rs][1]; 94 t[k][2]=t[ls][2]+t[rs][2]; 95 t[k][3]=t[ls][3]+t[rs][3]; 96 t[k][4]=t[ls][4]+t[rs][4]; 97 t[k][5]=t[ls][5]+t[rs][5]; 98 t[k][6]=t[ls][6]+t[rs][6]; 99 t[k][7]=t[ls][7]+t[rs][7]; 100 t[k][8]=t[ls][8]+t[rs][8]; 101 t[k][9]=t[ls][9]+t[rs][9]; 102 t[k][10]=t[ls][10]+t[rs][10]; 103 t[k][11]=t[ls][11]+t[rs][11]; 104 t[k][12]=t[ls][12]+t[rs][12]; 105 t[k][13]=t[ls][13]+t[rs][13]; 106 t[k][14]=t[ls][14]+t[rs][14]; 107 t[k][15]=t[ls][15]+t[rs][15]; 108 t[k][16]=t[ls][16]+t[rs][16]; 109 t[k][17]=t[ls][17]+t[rs][17]; 110 t[k][18]=t[ls][18]+t[rs][18]; 111 t[k][19]=t[ls][19]+t[rs][19]; 112 t[k][20]=t[ls][20]+t[rs][20]; 113 t[k][21]=t[ls][21]+t[rs][21]; 114 t[k][22]=t[ls][22]+t[rs][22]; 115 t[k][23]=t[ls][23]+t[rs][23]; 116 t[k][24]=t[ls][24]+t[rs][24]; 117 t[k][25]=t[ls][25]+t[rs][25]; 118 t[k][26]=t[ls][26]+t[rs][26]; 119 } 120 }T; 121 inline int Rd() 122 { 123 register int x=0,f=1;register char c=getchar(); 124 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 125 while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();} 126 return x*f; 127 } 128 int n,m; 129 int main() 130 { 131 scanf("%d%d%s",&n,&m,s); 132 T.Build(1,1,n); 133 while(m--) 134 { 135 memset(now,0,sizeof(now)); 136 register int l,r,x,t,k; 137 l=Rd();r=Rd();x=Rd(); 138 k=l; 139 T.query(1,1,n,l,r); 140 if(x) 141 { 142 t=1; 143 while(t<=26) 144 { 145 while(!now[t]&&t<=26)++t; 146 T.change(1,1,n,k,k+now[t]-1,t); 147 k+=now[t]; 148 now[t]=0; 149 } 150 } 151 else 152 { 153 t=26; 154 while(t>=0) 155 { 156 while(!now[t]&&t>=0)--t; 157 T.change(1,1,n,k,k+now[t]-1,t); 158 k+=now[t]; 159 now[t]=0; 160 } 161 } 162 } 163 for(int i=1;i<=n;i++) 164 { 165 memset(now,0,sizeof(now)); 166 T.query(1,1,n,i,i); 167 for(int j=1;j<=26;j++) 168 if(now[j]) 169 { 170 putchar('a'+j-1); 171 break; 172 } 173 } 174 puts(""); 175 return 0; 176 }

1 #include<cstdio> 2 char s[100005],bucx[100005];int bucr[100005],buc[127],n,m; 3 main(){ 4 scanf("%d%d%s",&n,&m,s+1);bucr[n+1]=n+1; 5 for(int i=1;i<=n;++i)bucr[i]=i,bucx[i]=s[i]; 6 for(int i=1,l,r,x;i<=m;++i){ 7 scanf("%d%d%d",&l,&r,&x); 8 int j;for(j=l;!bucr[j];--j); 9 int k=bucr[j]+1;if(j!=l)buc[bucx[j]]+=bucr[j]-l+1,bucr[j]=l-1;else k=j; 10 while(bucr[k]<=r){ 11 buc[bucx[k]]+=bucr[k]-k+1; 12 int lst=k;k=bucr[k]+1;bucr[lst]=0; 13 } 14 if(k<=r)buc[bucx[k]]+=r-k+1,bucr[r+1]=bucr[k],bucx[r+1]=bucx[k],bucr[k]=0; 15 if(x)for(char ch='a';ch<='z';++ch)if(buc[ch])bucr[l]=l+buc[ch]-1,bucx[l]=ch,l=bucr[l]+1,buc[ch]=0; 16 if(!x)for(char ch='z';ch>='a';--ch)if(buc[ch])bucr[l]=l+buc[ch]-1,bucx[l]=ch,l=bucr[l]+1,buc[ch]=0; 17 } 18 for(int i=1;i<=n;i=bucr[i]+1)for(int j=i;j<=bucr[i];++j)putchar(bucx[i]); 19 }
(Orz wd暴力QJ神仙打法)
T2:matrix
dp状态设的很神 f[i][j]表示前i列满足j个有区间且满足题意的方案数
先设ls[i]表示右端点在前i列的左区间的方案数,rs[i]表示左端点在前i列的右区间的方案数
然后就可以转移了,考虑列数增还是不增
不增:f[i+1][j]+=f[i][j]
增:f[i+1][j+1]+=f[i][j]*(rs[i+1]-j)
注意左侧区间我们并没有考虑,实际考虑,供我们选的列有i-j个,前一个状态已经选了ls[i-1]个,新增状态有ls[i]-ls[i-1]个。
用新增状态塞满可选状态并要考虑顺序,同时还有一个合法状态的判定然后就没啦
说起来很简单,但状态真的难想,但也不无道理。
这个题紧紧扣住列,而与具体是哪行无关,所以i,j都与列有关,同时为了方便转移,我们抓住一侧的区间,状态及其转移就显然了。
还是要抓住题目核心性质。

1 #include<bits/stdc++.h> 2 #define MAXN 3005 3 #define int long long 4 using namespace std; 5 const int mod=998244353; 6 int f[MAXN][MAXN],ls[MAXN],rs[MAXN],l[MAXN],r[MAXN],A[MAXN][MAXN]; 7 signed main() 8 { 9 int n,m; 10 scanf("%lld%lld",&n,&m); 11 for(int i=1;i<=n;i++) 12 { 13 scanf("%lld%lld",&l[i],&r[i]); 14 ls[l[i]]++;rs[r[i]]++; 15 } 16 for(int i=1;i<=m;i++)ls[i]+=ls[i-1],rs[i]+=rs[i-1]; 17 A[0][0]=A[0][1]=1;f[0][0]=1; 18 for(int i=1;i<=m;i++) 19 { 20 A[i][0]=1;A[i][1]=i; 21 for(int j=2;j<=i;j++) 22 A[i][j]=A[i][j-1]*(i-j+1)%mod; 23 } 24 for(int i=0;i<=m;i++) 25 { 26 for(int j=0;j<=min(i,n);j++) 27 { 28 if(i-j<ls[i])break; 29 (f[i][j]*=A[i-j-ls[i-1]][ls[i]-ls[i-1]])%=mod; 30 (f[i+1][j]+=f[i][j])%=mod; 31 (f[i+1][j+1]+=f[i][j]*max(0ll,rs[i+1]-j))%=mod; 32 } 33 } 34 cout<<f[m][n]<<endl; 35 return 0; 36 }
T3:big
这题的难点在于如何转化题意
这个式子实际上就是x的逻辑左移,然后后面就显然了,开一颗Trie树,求最大值即可

1 #include<bits/stdc++.h> 2 #define re register 3 using namespace std; 4 const int MAXN=100000; 5 int n,maxx,val,sum[MAXN],psum[MAXN],num; 6 int ch[MAXN*50][2],tot; 7 void insert(const int x) 8 { 9 re int p=0; 10 for(int i=n-1;i>=0;i--) 11 { 12 re int k=(x>>i)&1; 13 if(!ch[p][k])ch[p][k]=++tot; 14 p=ch[p][k]; 15 } 16 return ; 17 } 18 void Getans(const int x,int val,int dep) 19 { 20 if(!ch[x][0]&&!ch[x][1]) 21 { 22 if(val==maxx)num++; 23 else if(val>maxx)maxx=val,num=1; 24 return ; 25 } 26 if(ch[x][0]&&ch[x][1]){ 27 Getans(ch[x][0],val,dep+1); 28 Getans(ch[x][1],val,dep+1); 29 return ; 30 } 31 if(!ch[x][0]||!ch[x][1]){ 32 Getans(ch[x][0]|ch[x][1],val+(1<<(n-dep-1)),dep+1); 33 } 34 return ; 35 } 36 int main() 37 { 38 int m; 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=m;i++) 41 { 42 register int a,k=0;scanf("%d",&a); 43 sum[i]=sum[i-1]^a; 44 if((a>>(n-1))&1)k=1; 45 (k+=a<<1)&=((1<<n)-1); 46 psum[i]=psum[i-1]^k; 47 } 48 for(int i=0;i<=m;i++) 49 insert(psum[i]^(sum[m]^sum[i])); 50 Getans(0,0,0); 51 cout<<maxx<<endl<<num<<endl; 52 return 0; 53 }
总结:
1.分析题目核心性质
2.转化题意
3.卡常
来源:https://www.cnblogs.com/hzoi-kx/p/11286735.html