这次考试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.卡常