Xors on Segments Codeforces - 620F
http://codeforces.com/problemset/problem/620/F
此题是莫队,但是不能用一般的莫队做,因为是最优化问题,没有办法在删除元素的时候维护答案。
这题的方法(好像还有个名字叫"回滚莫队“,说明:https://blog.csdn.net/maverickfw/article/details/72988286):
官方题解:http://codeforces.com/blog/entry/22936
设完成一次"加入贡献"的操作的复杂度是O(p)
首先定块大小sz,定每个坐标应该属于的块。
对于左右端点在同一块内的询问,暴力处理即可。每一个询问需要复杂度O(p*sz)
对于其他询问,按左端点所属的块分类。
分类完后,对于同一类的询问,按右端点从小到大排序。对于每一类的询问分开处理。
对于每一类,先把"当前维护区间"的左端点定为 属于该块的坐标 中最靠右的坐标(这样的话,该类询问的左端点都小于等于这个点且离这个点距离不超过sz),右端点定为左端点-1(为了让区间为空)。还要清空当前答案。
对于该类中每一个询问,先照常移动右端点到与询问的右端点相同,然后记下此时的答案,然后把左端点移动到与询问的左端点相同,得到该询问的答案并记录;然后把左端点的移动还原,把答案还原即可(这样就避开了维护答案)
对于每一类,右端点最多有O(n)次移动,而有n/sz类,这一部分复杂度是O(p*n*n/sz);对于每一个询问,额外还要O(p*sz)的复杂度进行左端点的调整
因此,总复杂度是O(p*(n*n/sz+m*sz)),当sz=sqrt(n*n/m)时最小
解决了莫队的问题,还要解决异或最大值维护的问题。这个是用01字典树做的,就不写了。。。看官方题解吧
(大概要支持在01字典树中查询:集合中,对于所有"第二权值"小于等于/大于等于特定值的元素,查询与另一给定值异或的最大值,挺奇怪的)
错误记录:
1.trie没有开垃圾回收,内存不够
2.计算块大小时,没有注意块大小可能变成0
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<set> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 int f[2000100]; 9 int n,m,sz,sz1; 10 //int ttt; 11 int lft[40]; 12 namespace Trie 13 { 14 const int l2n=20; 15 int sz[4000100],ch[4000100][2],dat[4000100]; 16 multiset<int> ss[4001000]; 17 int x,kkk; 18 queue<int> qqq; 19 int getnode() 20 { 21 //yttt=max(ttt,int(2000100-qqq.size())); 22 int t=qqq.front();qqq.pop(); 23 return t; 24 } 25 void delnode(int x) 26 { 27 qqq.push(x); 28 } 29 void deltree(int x) 30 { 31 if(!x) return; 32 deltree(ch[x][0]); 33 deltree(ch[x][1]); 34 ss[x].clear();ch[x][0]=ch[x][1]=dat[x]=sz[x]=0; 35 delnode(x); 36 } 37 void init() 38 { 39 int i; 40 for(i=1;i<4000100;i++) qqq.push(i); 41 lft[0]=1; 42 for(i=1;i<=l2n;i++) lft[i]=lft[i-1]<<1; 43 } 44 int getdat1(int x) {return x?dat[x]:0x3f3f3f3f;} 45 void _ins1(int p,int &num) 46 { 47 if(!num) num=getnode(),dat[num]=0x3f3f3f3f; 48 sz[num]++; 49 if(p>=0) _ins1(p-1,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][0]),getdat1(ch[num][1])); 50 else ss[num].insert(kkk),dat[num]=*ss[num].begin(); 51 } 52 void ins1(int d,int kk,int &num) {x=d;kkk=kk;_ins1(l2n-1,num);} 53 //ins1维护插入kk的最小值 54 void _ins2(int p,int &num) 55 { 56 if(!num) num=getnode(); 57 sz[num]++; 58 if(p>=0) _ins2(p-1,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][0]],dat[ch[num][1]]); 59 else ss[num].insert(kkk),dat[num]=*ss[num].rbegin(); 60 } 61 void ins2(int d,int kk,int &num) {x=d;kkk=kk;_ins2(l2n-1,num);} 62 //ins2维护插入kk的最大值 63 64 65 void _era1(int p,int &num) 66 { 67 sz[num]--; 68 if(p>=0) _era1(p-1,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][0]),getdat1(ch[num][1])); 69 else ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?0x3f3f3f3f:*ss[num].begin(); 70 } 71 void era1(int d,int kk,int &num) {x=d;kkk=kk;_era1(l2n-1,num);} 72 void _era2(int p,int &num) 73 { 74 sz[num]--; 75 if(p>=0) _era2(p-1,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][0]],dat[ch[num][1]]); 76 else ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?0:*ss[num].rbegin(); 77 } 78 void era2(int d,int kk,int &num) {x=d;kkk=kk;_era2(l2n-1,num);} 79 80 81 int que1(int x,int kk,int num)//que1查询维护值小于等于kk的数中与x的xor最大值 82 { 83 int ans=0,i;bool t; 84 for(i=l2n-1;i>=0;--i) 85 { 86 t=x&lft[i]; 87 if(sz[ch[num][!t]]&&dat[ch[num][!t]]<=kk) ans|=lft[i],num=ch[num][!t]; 88 else num=ch[num][t]; 89 } 90 return ans; 91 } 92 int que2(int x,int kk,int num)//que2查询维护值大于等于kk的数中与x的xor最大值 93 { 94 int ans=0,i;bool t; 95 for(i=l2n-1;i>=0;--i) 96 { 97 t=x&lft[i]; 98 if(sz[ch[num][!t]]&&dat[ch[num][!t]]>=kk) ans|=lft[i],num=ch[num][!t]; 99 else num=ch[num][t]; 100 } 101 return ans; 102 } 103 } 104 using Trie::ins1;using Trie::ins2; 105 using Trie::era1;using Trie::era2; 106 using Trie::que1;using Trie::que2; 107 using Trie::deltree; 108 struct Q 109 { 110 int l,r,num; 111 Q(){} 112 Q(int a,int b,int c):l(a),r(b),num(c){} 113 }; 114 int a[50100],ans[5010]; 115 int rt1,rt2; 116 int anss; 117 void add1(int p)//加入p的贡献 118 { 119 ins1(f[p-1],p,rt1);ins2(f[p],p,rt2); 120 anss=max(anss,que1(f[p],p,rt1)); 121 //printf("a%d\n",f[p]^f[p-1]); 122 anss=max(anss,que2(f[p-1],p,rt2)); 123 } 124 void del1(int p) 125 { 126 era1(f[p-1],p,rt1);era2(f[p],p,rt2); 127 } 128 vector<Q> q[1010]; 129 bool cmp(const Q &a,const Q &b) {return a.r<b.r;} 130 int main() 131 { 132 int i,j,j2,l,r,tans;Trie::init(); 133 for(i=1;i<=2000000;i++) f[i]=f[i-1]^i; 134 scanf("%d%d",&n,&m);sz=max(1,int(sqrt(double(n)/m*n)));sz1=(n-1)/sz; 135 for(i=1;i<=n;i++) scanf("%d",&a[i]); 136 for(i=1;i<=m;i++) 137 { 138 scanf("%d%d",&l,&r); 139 if((l-1)/sz==(r-1)/sz) 140 { 141 deltree(rt1);deltree(rt2); 142 rt1=rt2=anss=0; 143 for(j=l;j<=r;j++) add1(a[j]); 144 ans[i]=anss; 145 //printf("a%d %d\n",i,ans[i]); 146 } 147 else 148 q[(l-1)/sz].push_back(Q(l,r,i)); 149 } 150 for(i=0;i<=sz1;i++) 151 { 152 sort(q[i].begin(),q[i].end(),cmp); 153 l=(i+1)*sz;r=l-1;rt1=rt2=anss=0; 154 for(j=0;j<q[i].size();j++) 155 { 156 while(r<q[i][j].r) add1(a[++r]); 157 tans=anss; 158 for(j2=l-1;j2>=q[i][j].l;j2--) add1(a[j2]); 159 ans[q[i][j].num]=anss; 160 for(j2=l-1;j2>=q[i][j].l;j2--) del1(a[j2]); 161 anss=tans; 162 } 163 deltree(rt1);deltree(rt2); 164 } 165 for(i=1;i<=m;i++) printf("%d\n",ans[i]); 166 //printf("a%d\n",ttt); 167 return 0; 168 }