noip模拟测试11

时间:2022-12-17 10:17:19

T1:string

  第一眼秒出思路,这不就是排序那道题的加强版吗?

  然而歪?解复杂度虽然是对的,但常数过大,竟被卡到70

  歪?解:(实际上std写的就是这个,但据说std被卡掉了 OAO)

    因为字符集很小,所以我们可以把区间排序改为区间查询和覆盖

    即:先查询区间内所有字符的个数,再从左端点开始按照大小关系依次将长度为字符个数的区间修改为该字符。

    期望复杂度O ( 26*mlogn ),实际复杂度O ( 26*mlogn*(巨大的常数) )

    所以需要一(feng)定(kuang)的卡常

  正?解:

    因为字符集很小,所以重复字符很多,又因为我们的操作是排序,所以操作后字符显然会变为一块一块的

    所以可以在线段树上每个节点记录段内字符是否全部相等

    若相等直接return,否则向下递归

    这样直接递归看起来似乎单次复杂度不太对

    但是仔细一想会发现,对于较短的区间操作来说,整块字符较少,递归次数较多,但区间短,所以复杂度正确

              对于较长的区间操作来说,整块字符较多,递归次数较少,虽区间长,但复杂度仍正确

    所以均摊复杂度正确,可过(还跑的挺快???)

    

    so,歪?解 code

noip模拟测试11noip模拟测试11
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 using namespace std;
 9 const int MAXN=100105;
10 int n,m,tmp[30],ls[MAXN*2],rs[MAXN*2],sum[MAXN*2][26],tag[MAXN*2],tot,lst,root;
11 char s[MAXN];
12 void build(int &p,int l,int r) {
13     if(!p) p=++tot;
14     if(l==r) return (void) (sum[p][s[l]-'a'+1]=1);
15     int mid=(l+r)>>1;
16     build(ls[p],l,mid),build(rs[p],mid+1,r);
17     for(int i=1;i<=26;i++) sum[p][i]=sum[ls[p]][i]+sum[rs[p]][i];
18 }
19 int ask(int p,int l,int r,int ql,int qr,int k) {
20     if(ql==l&&qr==r) return sum[p][k];
21     int mid=(l+r)>>1;
22     if(tag[p]) {
23         for(int i=1;i<=26;i++) sum[ls[p]][i]=0; 
24         for(int i=1;i<=26;i++) sum[rs[p]][i]=0;
25         sum[ls[p]][tag[p]]=mid-l+1;
26         sum[rs[p]][tag[p]]=r-mid;
27         tag[ls[p]]=tag[rs[p]]=tag[p];
28         tag[p]=0;
29     }
30     if(qr<=mid) return ask(ls[p],l,mid,ql,qr,k);
31     else if(ql>mid) return ask(rs[p],mid+1,r,ql,qr,k);
32     else return ask(ls[p],l,mid,ql,mid,k)+ask(rs[p],mid+1,r,mid+1,qr,k);
33 }
34 void change(int p,int l,int r,int ql,int qr,int k) {
35     if(ql==l&&qr==r) {
36         for(int i=1;i<=26;i++) sum[p][i]=0;
37         sum[p][k]=r-l+1; tag[p]=k;
38         return;
39     }
40     int mid=(l+r)>>1;
41     if(tag[p]) {
42         for(int i=1;i<=26;i++) sum[ls[p]][i]=0; 
43         for(int i=1;i<=26;i++) sum[rs[p]][i]=0;
44         sum[ls[p]][tag[p]]=mid-l+1;
45         sum[rs[p]][tag[p]]=r-mid;
46         tag[ls[p]]=tag[rs[p]]=tag[p];
47         tag[p]=0;
48     }
49     if(qr<=mid) change(ls[p],l,mid,ql,qr,k);
50     else if(ql>mid) change(rs[p],mid+1,r,ql,qr,k);
51     else change(ls[p],l,mid,ql,mid,k),change(rs[p],mid+1,r,mid+1,qr,k);
52     for(int i=1;i<=26;i++) sum[p][i]=sum[ls[p]][i]+sum[rs[p]][i];
53 }
54 void print(int p,int l,int r) {
55     if(l==r) {
56         for(int i=1;i<=26;i++)
57             if(sum[p][i]) printf("%c",i+'a'-1);
58         return;
59     }
60     int mid=(l+r)>>1;
61     if(tag[p]) {
62         for(int i=1;i<=26;i++) sum[ls[p]][i]=0; 
63         for(int i=1;i<=26;i++) sum[rs[p]][i]=0;
64         sum[ls[p]][tag[p]]=mid-l+1;
65         sum[rs[p]][tag[p]]=r-mid;
66         tag[ls[p]]=tag[rs[p]]=tag[p];
67         tag[p]=0;
68     }
69     print(ls[p],l,mid),print(rs[p],mid+1,r);
70 }
71 int main() {
72     scanf("%d%d%s",&n,&m,s+1);
73     build(root,1,n);
74     for(int i=1,o,tl,tr;i<=m;i++) {
75         scanf("%d%d%d",&tl,&tr,&o);
76         lst=tl;
77         for(int j=1;j<=26;j++) tmp[j]=ask(root,1,n,tl,tr,j);
78         if(!o) {
79             for(int j=26;j>=1;j--)
80                 if(tmp[j]) {
81                     change(root,1,n,lst,lst+tmp[j]-1,j);
82                     lst+=tmp[j];
83                 }
84         } else {
85             for(int j=1;j<=26;j++)
86                 if(tmp[j]) {
87                     change(root,1,n,lst,lst+tmp[j]-1,j);
88                     lst+=tmp[j];
89                 }
90         }
91     }
92     print(root,1,n);
93     printf("\n");
94     return 0;
95 }
t1 不卡常 Code
noip模拟测试11noip模拟测试11
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<cmath>
  8 using namespace std;
  9 const int MAXN=100001;
 10 int n,m,tmp[30],ls[MAXN*2],rs[MAXN*2],sum[MAXN*2][26],tag[MAXN*2],tot,lst,root;
 11 char s[MAXN];
 12 void build(int &p,int l,int r) {
 13     if(!p) p=++tot;
 14     if(l==r) return (void) (sum[p][s[l]-'a'+1]=1);
 15     int mid=(l+r)>>1;
 16     build(ls[p],l,mid),build(rs[p],mid+1,r);
 17     sum[p][1]=sum[ls[p]][1]+sum[rs[p]][1];sum[p][2]=sum[ls[p]][2]+sum[rs[p]][2];
 18     sum[p][3]=sum[ls[p]][3]+sum[rs[p]][3];sum[p][4]=sum[ls[p]][4]+sum[rs[p]][4];
 19     sum[p][5]=sum[ls[p]][5]+sum[rs[p]][5];sum[p][6]=sum[ls[p]][6]+sum[rs[p]][6];
 20     sum[p][7]=sum[ls[p]][7]+sum[rs[p]][7];sum[p][8]=sum[ls[p]][8]+sum[rs[p]][8];
 21     sum[p][9]=sum[ls[p]][9]+sum[rs[p]][9];sum[p][10]=sum[ls[p]][10]+sum[rs[p]][10];
 22     sum[p][11]=sum[ls[p]][11]+sum[rs[p]][11];sum[p][12]=sum[ls[p]][12]+sum[rs[p]][12];
 23     sum[p][13]=sum[ls[p]][13]+sum[rs[p]][13];sum[p][14]=sum[ls[p]][14]+sum[rs[p]][14];
 24     sum[p][15]=sum[ls[p]][15]+sum[rs[p]][15];sum[p][16]=sum[ls[p]][16]+sum[rs[p]][16];
 25     sum[p][17]=sum[ls[p]][17]+sum[rs[p]][17];sum[p][18]=sum[ls[p]][18]+sum[rs[p]][18];
 26     sum[p][19]=sum[ls[p]][19]+sum[rs[p]][19];sum[p][20]=sum[ls[p]][20]+sum[rs[p]][20];
 27     sum[p][21]=sum[ls[p]][21]+sum[rs[p]][21];sum[p][22]=sum[ls[p]][22]+sum[rs[p]][22];
 28     sum[p][23]=sum[ls[p]][23]+sum[rs[p]][23];sum[p][24]=sum[ls[p]][24]+sum[rs[p]][24];
 29     sum[p][25]=sum[ls[p]][25]+sum[rs[p]][25];sum[p][26]=sum[ls[p]][26]+sum[rs[p]][26];
 30 }
 31 void ask(int p,int l,int r,int ql,int qr) {
 32     if(ql==l&&qr==r) {
 33         tmp[1]+=sum[p][1];tmp[2]+=sum[p][2];tmp[3]+=sum[p][3];tmp[4]+=sum[p][4];
 34         tmp[5]+=sum[p][5];tmp[6]+=sum[p][6];tmp[7]+=sum[p][7];tmp[8]+=sum[p][8];
 35         tmp[9]+=sum[p][9];tmp[10]+=sum[p][10];tmp[11]+=sum[p][11];tmp[12]+=sum[p][12];
 36         tmp[13]+=sum[p][13];tmp[14]+=sum[p][14];tmp[15]+=sum[p][15];tmp[16]+=sum[p][16];
 37         tmp[17]+=sum[p][17];tmp[18]+=sum[p][18];tmp[19]+=sum[p][19];tmp[20]+=sum[p][20];
 38         tmp[21]+=sum[p][21];tmp[22]+=sum[p][22];tmp[23]+=sum[p][23];tmp[24]+=sum[p][24];
 39         tmp[25]+=sum[p][25];tmp[26]+=sum[p][26];
 40         return;
 41     }
 42     int mid=(l+r)>>1;
 43     if(tag[p]) {
 44         sum[ls[p]][1]=0;sum[ls[p]][2]=0;sum[ls[p]][3]=0;sum[ls[p]][4]=0;
 45         sum[ls[p]][5]=0;sum[ls[p]][6]=0;sum[ls[p]][7]=0;sum[ls[p]][8]=0;
 46         sum[ls[p]][9]=0;sum[ls[p]][10]=0;sum[ls[p]][11]=0;sum[ls[p]][12]=0;
 47         sum[ls[p]][13]=0;sum[ls[p]][14]=0;sum[ls[p]][15]=0;sum[ls[p]][16]=0;
 48         sum[ls[p]][17]=0;sum[ls[p]][18]=0;sum[ls[p]][19]=0;sum[ls[p]][20]=0;
 49         sum[ls[p]][21]=0;sum[ls[p]][22]=0;sum[ls[p]][23]=0;sum[ls[p]][24]=0;
 50         sum[ls[p]][25]=0;sum[ls[p]][26]=0;
 51         sum[rs[p]][1]=0;sum[rs[p]][2]=0;sum[rs[p]][3]=0;sum[rs[p]][4]=0;
 52         sum[rs[p]][5]=0;sum[rs[p]][6]=0;sum[rs[p]][7]=0;sum[rs[p]][8]=0;
 53         sum[rs[p]][9]=0;sum[rs[p]][10]=0;sum[rs[p]][11]=0;sum[rs[p]][12]=0;
 54         sum[rs[p]][13]=0;sum[rs[p]][14]=0;sum[rs[p]][15]=0;sum[rs[p]][16]=0;
 55         sum[rs[p]][17]=0;sum[rs[p]][18]=0;sum[rs[p]][19]=0;sum[rs[p]][20]=0;
 56         sum[rs[p]][21]=0;sum[rs[p]][22]=0;sum[rs[p]][23]=0;sum[rs[p]][24]=0;
 57         sum[rs[p]][25]=0;sum[rs[p]][26]=0;
 58         sum[ls[p]][tag[p]]=mid-l+1;
 59         sum[rs[p]][tag[p]]=r-mid;
 60         tag[ls[p]]=tag[rs[p]]=tag[p];
 61         tag[p]=0;
 62     }
 63     if(qr<=mid) ask(ls[p],l,mid,ql,qr);
 64     else if(ql>mid) ask(rs[p],mid+1,r,ql,qr);
 65     else ask(ls[p],l,mid,ql,mid),ask(rs[p],mid+1,r,mid+1,qr);
 66 }
 67 void change(int p,int l,int r,int ql,int qr,int k) {
 68     if(ql==l&&qr==r) {
 69         sum[p][1]=0;sum[p][2]=0;sum[p][3]=0;sum[p][4]=0;
 70         sum[p][5]=0;sum[p][6]=0;sum[p][7]=0;sum[p][8]=0;
 71         sum[p][9]=0;sum[p][10]=0;sum[p][11]=0;sum[p][12]=0;
 72         sum[p][13]=0;sum[p][14]=0;sum[p][15]=0;sum[p][16]=0;
 73         sum[p][17]=0;sum[p][18]=0;sum[p][19]=0;sum[p][20]=0;
 74         sum[p][21]=0;sum[p][22]=0;sum[p][23]=0;sum[p][24]=0;
 75         sum[p][25]=0;sum[p][26]=0;
 76         sum[p][k]=r-l+1; tag[p]=k;
 77         return;
 78     }
 79     int mid=(l+r)>>1;
 80     if(tag[p]) {
 81         sum[ls[p]][1]=0;sum[ls[p]][2]=0;sum[ls[p]][3]=0;sum[ls[p]][4]=0;
 82         sum[ls[p]][5]=0;sum[ls[p]][6]=0;sum[ls[p]][7]=0;sum[ls[p]][8]=0;
 83         sum[ls[p]][9]=0;sum[ls[p]][10]=0;sum[ls[p]][11]=0;sum[ls[p]][12]=0;
 84         sum[ls[p]][13]=0;sum[ls[p]][14]=0;sum[ls[p]][15]=0;sum[ls[p]][16]=0;
 85         sum[ls[p]][17]=0;sum[ls[p]][18]=0;sum[ls[p]][19]=0;sum[ls[p]][20]=0;
 86         sum[ls[p]][21]=0;sum[ls[p]][22]=0;sum[ls[p]][23]=0;sum[ls[p]][24]=0;
 87         sum[ls[p]][25]=0;sum[ls[p]][26]=0;
 88         sum[rs[p]][1]=0;sum[rs[p]][2]=0;sum[rs[p]][3]=0;sum[rs[p]][4]=0;
 89         sum[rs[p]][5]=0;sum[rs[p]][6]=0;sum[rs[p]][7]=0;sum[rs[p]][8]=0;
 90         sum[rs[p]][9]=0;sum[rs[p]][10]=0;sum[rs[p]][11]=0;sum[rs[p]][12]=0;
 91         sum[rs[p]][13]=0;sum[rs[p]][14]=0;sum[rs[p]][15]=0;sum[rs[p]][16]=0;
 92         sum[rs[p]][17]=0;sum[rs[p]][18]=0;sum[rs[p]][19]=0;sum[rs[p]][20]=0;
 93         sum[rs[p]][21]=0;sum[rs[p]][22]=0;sum[rs[p]][23]=0;sum[rs[p]][24]=0;
 94         sum[rs[p]][25]=0;sum[rs[p]][26]=0;
 95         sum[ls[p]][tag[p]]=mid-l+1;
 96         sum[rs[p]][tag[p]]=r-mid;
 97         tag[ls[p]]=tag[rs[p]]=tag[p];
 98         tag[p]=0;
 99     }
100     if(qr<=mid) change(ls[p],l,mid,ql,qr,k);
101     else if(ql>mid) change(rs[p],mid+1,r,ql,qr,k);
102     else change(ls[p],l,mid,ql,mid,k),change(rs[p],mid+1,r,mid+1,qr,k);
103     sum[p][1]=sum[ls[p]][1]+sum[rs[p]][1];sum[p][2]=sum[ls[p]][2]+sum[rs[p]][2];
104     sum[p][3]=sum[ls[p]][3]+sum[rs[p]][3];sum[p][4]=sum[ls[p]][4]+sum[rs[p]][4];
105     sum[p][5]=sum[ls[p]][5]+sum[rs[p]][5];sum[p][6]=sum[ls[p]][6]+sum[rs[p]][6];
106     sum[p][7]=sum[ls[p]][7]+sum[rs[p]][7];sum[p][8]=sum[ls[p]][8]+sum[rs[p]][8];
107     sum[p][9]=sum[ls[p]][9]+sum[rs[p]][9];sum[p][10]=sum[ls[p]][10]+sum[rs[p]][10];
108     sum[p][11]=sum[ls[p]][11]+sum[rs[p]][11];sum[p][12]=sum[ls[p]][12]+sum[rs[p]][12];
109     sum[p][13]=sum[ls[p]][13]+sum[rs[p]][13];sum[p][14]=sum[ls[p]][14]+sum[rs[p]][14];
110     sum[p][15]=sum[ls[p]][15]+sum[rs[p]][15];sum[p][16]=sum[ls[p]][16]+sum[rs[p]][16];
111     sum[p][17]=sum[ls[p]][17]+sum[rs[p]][17];sum[p][18]=sum[ls[p]][18]+sum[rs[p]][18];
112     sum[p][19]=sum[ls[p]][19]+sum[rs[p]][19];sum[p][20]=sum[ls[p]][20]+sum[rs[p]][20];
113     sum[p][21]=sum[ls[p]][21]+sum[rs[p]][21];sum[p][22]=sum[ls[p]][22]+sum[rs[p]][22];
114     sum[p][23]=sum[ls[p]][23]+sum[rs[p]][23];sum[p][24]=sum[ls[p]][24]+sum[rs[p]][24];
115     sum[p][25]=sum[ls[p]][25]+sum[rs[p]][25];sum[p][26]=sum[ls[p]][26]+sum[rs[p]][26];
116 }
117 void print(int p,int l,int r) {
118     if(l==r) {
119         if(sum[p][1]) printf("a");
120         else if(sum[p][2]) printf("b");        else if(sum[p][3]) printf("c");
121         else if(sum[p][4]) printf("d");        else if(sum[p][5]) printf("e");
122         else if(sum[p][6]) printf("f");        else if(sum[p][7]) printf("g");
123         else if(sum[p][8]) printf("h");        else if(sum[p][9]) printf("i");
124         else if(sum[p][10]) printf("j");    else if(sum[p][11]) printf("k");
125         else if(sum[p][12]) printf("l");    else if(sum[p][13]) printf("m");
126         else if(sum[p][14]) printf("n");    else if(sum[p][15]) printf("o");
127         else if(sum[p][16]) printf("p");    else if(sum[p][17]) printf("q");
128         else if(sum[p][18]) printf("r");    else if(sum[p][19]) printf("s");
129         else if(sum[p][20]) printf("t");    else if(sum[p][21]) printf("u");
130         else if(sum[p][22]) printf("v");    else if(sum[p][23]) printf("w");
131         else if(sum[p][24]) printf("x");    else if(sum[p][25]) printf("y");
132         else if(sum[p][26]) printf("z");
133         return;
134     }
135     int mid=(l+r)>>1;
136     if(tag[p]) {
137         for(int i=l;i<=r;i++)
138             printf("%c",tag[p]+'a'-1);
139         return ;
140     }
141     print(ls[p],l,mid),print(rs[p],mid+1,r);
142 }
143 inline int R() {
144     int a=0;char c=getchar();
145     while(c>'9'||c<'0') c=getchar();
146     while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();
147     return a;
148 }
149 inline void read() {
150     char c=getchar(); int pos=0;
151     while(c<'a'||c>'z') c=getchar();
152     while(c>='a'&&c<='z') s[++pos]=c,c=getchar();
153 }
154 int main() {
155     n=R();m=R();read();
156     build(root,1,n);
157     for(register int i=1,o,tl,tr;i<=m;i++) {
158         lst=tl=R();tr=R();o=R();
159         memset(tmp,0,sizeof(tmp));
160         ask(root,1,n,tl,tr);
161         if(!o) {
162             for(int j=26;j>=1;j--)
163                 if(tmp[j]) {
164                     change(root,1,n,lst,lst+tmp[j]-1,j);
165                     lst+=tmp[j];
166                 }
167         } else {
168             for(int j=1;j<=26;j++)
169                 if(tmp[j]) {
170                     change(root,1,n,lst,lst+tmp[j]-1,j);
171                     lst+=tmp[j];
172                 }
173         }
174     }
175     print(root,1,n);
176     printf("\n");
177     return 0;
178 }
t1 卡常 Code

 


T2:matrix

  是语文神题(可能是我语文太菜,不像某 sto~CWY~orz)

  先说说坑点,每行的 l 到 r 之间不能有 1 !!!

  TAT

  说说正解吧:

    考虑到如果从左向右计算答案左区间的方案可以直接计算,而右区间不好计算,所以设计dp状态:

    $f [ i ][ j ]$表示考虑到第 i 列,在开始点在 i 之前的右区间内放了 j 个 1 的方案数

    考虑转移:

    首先求出两个数组 l 和 r,分别表示左区间的结束点在1到 l 的区间个数和右区间的开始点在 1 到 r 的区间个数

    先考虑放在左区间或不放的情况:

      对于 $l [ i ] == l [ i - 1 ]$的情况,说明该位置没有新的左区间结束,所以$f [ i ][ j ]=f [ i - 1 ][ j ]$

      对于 $l [ i ] != l [ i - 1 ]$的情况,说明该位置有新的左区间结束,所以要乘上安排所有左区间的方案数

        总共有 $l [ i ] - l [ i - 1 ]$个左区间需要安排 1 ,之前还空着的列有 $i - j - l [ i - 1 ]$ 个

        所以安排左区间的方案数为$P^{l[i]-l[i-1]}_{i-j-l[i-1]}$

        所以$f [ i ][ j ]=f [ i - 1 ][ j ]*P^{l[i]-l[i-1]}_{i-j-l[i-1]}$

    再考虑放在右区间的情况:

      如果$j>0$那么$f[i][j]$可以由$f[i-1][j-1]$转移而来

      总共有$r[i]$行,放了$j-1$行,还剩$r[i]-j$行

      考虑将新的一个1放在哪一行,并且将方案数乘上新结束的左区间的方案数,得到答案

      所以$f [ i ][ j ]+=f [ i - 1 ][ j-1 ]*[r[i]-(j-1)]*P^{l[i]-l[i-1]}_{i-j-l[i-1]}$

    这样就转移完了,最终答案为$f[m][n]$,即考虑完m列有n个1放在右区间的方案数

    

    so,code

noip模拟测试11noip模拟测试11
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 #define ll long long
 9 using namespace std;
10 const int MAXN=4005,D=998244353;
11 int n,m,l[MAXN],r[MAXN];
12 ll ans,f[MAXN][MAXN],fac[MAXN],inv[MAXN];
13 ll qpow(ll x,ll k) {
14     ll ret=1;
15     while(k) {
16         if(k&1) ret=ret*x%D;
17         x=x*x%D;
18         k>>=1;
19     }
20     return ret;
21 }
22 void first() {
23     fac[0]=inv[0]=1;
24     for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%D;
25     inv[m]=qpow(fac[m],D-2);
26     for(int i=m-1;i>=1;i--) inv[i]=inv[i+1]*(i+1)%D;
27 }
28 ll A(ll x,ll y) {
29     return fac[x]*inv[x-y]%D;
30 }
31 int main() {
32     scanf("%d%d",&n,&m);
33     for(int i=1,aa,bb;i<=n;i++) {
34         scanf("%d%d",&aa,&bb);
35         ++l[aa];++r[bb];
36     }
37     first();
38     for(int i=1;i<=m;i++) l[i]+=l[i-1];
39     for(int i=1;i<=m;i++) r[i]+=r[i-1];
40     f[0][0]=1;
41     for(int i=1;i<=m;i++) {
42         for(int j=0;j<=r[i];j++) {
43             if(l[i]==l[i-1]) f[i][j]=f[i-1][j];
44             else f[i][j]=f[i-1][j]*A(i-j-l[i-1],l[i]-l[i-1])%D;
45             if(j) f[i][j]=(f[i][j]+f[i-1][j-1]*(r[i]-j+1)%D*A(i-j-l[i-1],l[i]-l[i-1])%D)%D;
46         }
47     }
48     printf("%lld\n",(f[m][n]%D+D)%D);
49     return 0;
50 }
t2 Code

 


 

T3:big

  看错第二问我也是醉了……

  首先要理解对手的操作是将你的数字左移一位,并将最高位放到最低位

  那么我们容易(?)想到从中间k时刻操作相当于将x和前k位全部操作

  所以可以将操作转化为将前k个数操作后再将整个数列异或起来

  如果我们枚举所有的k值进行预处理,得到$m+1$个数,记作b数组

  那么我们的问题就变为了选择一个数x,使其异或b数组的最小值最大

  

  这就很容易想到用tire树来做了

  对于b数组,我们构建一颗01tire树

  考虑如何获得最大的答案

  我们dfs这颗tire树,对于任意节点p来说:

    如果p同时拥有两个儿子,那么无论我们如何构造x,对手一定能将这一位变为0,所以答案这一位为0

    如果p只有一个儿子,那么我们一定可以构造出一个x,使答案的这一位为1,所以答案这一位为1

  所以一边记录最大值一边统计个数就完了

  

  so,code

  

noip模拟测试11noip模拟测试11
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 using namespace std;
 9 const int MAXN=100005;
10 int n,m,a[MAXN],s[MAXN],ans1,ans2,b[MAXN],ch[MAXN*30][2],tot=1,root=1;
11 int calc(int x) {
12     return ((x>>(n-1))+((x&(~(1<<(n-1))))<<1));
13 }
14 void insert(int x) {
15     int p=root;
16     for(int i=n;i>=1;i--) {
17         if(!ch[p][(x>>(i-1))&1]) ch[p][(x>>(i-1))&1]=++tot;
18         p=ch[p][(x>>(i-1))&1];
19     }
20 }
21 void dfs(int u,int x,int t) {
22     if(t==0) {
23         if(x>ans1) {
24             ans1=x;
25             ans2=1;
26         } else if(ans1==x) ans2++;
27         return;
28     }
29     if(ch[u][0]&&ch[u][1]) {
30         dfs(ch[u][0],x,t-1);
31         dfs(ch[u][1],x,t-1);
32     } else {
33         if(ch[u][0]) dfs(ch[u][0],(x|(1<<(t-1))),t-1);
34         else dfs(ch[u][1],(x|(1<<(t-1))),t-1);
35     }
36 }
37 int main() {
38     scanf("%d%d",&n,&m);
39     for(int i=1;i<=m;i++) scanf("%d",&a[i]);
40     for(int i=1;i<=m;i++) s[i]=s[i-1]^a[i];
41     for(int i=0;i<=m;i++) insert(calc(s[i])^(s[m]^s[i]));
42     dfs(root,0,n);
43     printf("%d\n%d\n",ans1,ans2);
44     return 0;
45 }
t3 Code