洛谷 P4585 [FJOI2015]火星商店问题
Posted 哈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P4585 [FJOI2015]火星商店问题相关的知识,希望对你有一定的参考价值。
(勿看,仅作笔记)
bzoj权限题。。。
https://www.luogu.org/problemnew/show/P4585
对于特殊商品,直接可持久化trie处理一下即可
剩下的,想了一段时间cdq,但是没想出来。。。应该是不行的
事实上,如果询问的不是最大值,而是一些满足[l,r]的答案等于[1,r]的答案-[1,l-1]的答案的东西,那么的确可以每个询问拆成两个直接cdq。。。
但是这题就不能。。不过可以线段树分治,这是基于[l,r]的答案可以被分成多个线段树上区间(这些区间的并等于[l,r])的答案的最大值
此题应该也可以线段树套可持久化trie做,但是最大的问题是垃圾回收。。。估计要写基于引用计数的垃圾回收?或者根本写不了?但是用分治的话只要每次solve之后把这次solve中用到的点全部回收掉就行了
跟题解学了个技巧:把询问和修改分开放进两个数组,方便处理
貌似那个vector也是可以去掉的,常数可以变小
使用vector是因为一个区间询问可能同时被分进两个子区间
那么只要处理出应该被分进左子区间的,然后solve左子区间,然后处理出应该被分进右子区间的,然后solve右子区间就行了;不一定要同时把应该分进左右子区间的处理出来
曾经错误:空间只算了后面solve部分所用字典树的空间,无视了特殊商品所占用的空间
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 #include<queue> 6 #include<map> 7 #define pb push_back 8 using namespace std; 9 namespace T 10 { 11 const int l2n=18; 12 int lft[40]; 13 int sz[3600100],ch[3600100][2]; 14 int x; 15 int st[3600200],top; 16 void init() 17 { 18 int i;lft[0]=1; 19 for(i=1;i<=l2n;i++) lft[i]=lft[i-1]<<1; 20 for(i=1;i<3600100;i++) st[++top]=i; 21 } 22 int getnode() 23 { 24 int t=st[top--];sz[t]=ch[t][0]=ch[t][1]=0; 25 return t; 26 } 27 void delnode(int x) {st[++top]=x;} 28 inline void cp(int &num) 29 { 30 int t=num;num=getnode();sz[num]=sz[t];ch[num][0]=ch[t][0];ch[num][1]=ch[t][1]; 31 } 32 void _ins(int p,int &num) 33 { 34 cp(num);sz[num]++; 35 if(p>=0) _ins(p-1,ch[num][!!(x&lft[p])]); 36 } 37 void ins(int d,int &num) {x=d;_ins(l2n-1,num);} 38 int que(int x,int r1,int r2) 39 { 40 int ans=0,i;bool t; 41 for(i=l2n-1;i>=0;i--) 42 { 43 t=x&lft[i]; 44 if(sz[ch[r2][!t]]-sz[ch[r1][!t]]) ans|=lft[i],r2=ch[r2][!t],r1=ch[r1][!t]; 45 else r2=ch[r2][t],r1=ch[r1][t]; 46 } 47 return ans; 48 } 49 } 50 int n,m; 51 int rt[100100]; 52 int ans[100100]; 53 struct Q 54 { 55 bool type; 56 int L,R,x,l,r,num; 57 }; 58 bool c1(const Q &a,const Q &b) {return a.L<b.L;} 59 vector<Q> qq0,qq1; 60 void solve(const vector<Q> &q,const vector<Q> &c,int l,int r) 61 { 62 int i; 63 int qz=q.size(),cz=c.size(); 64 map<int,int> rtt;rtt[0]=0;int rt1,rt2=0,tmem=T::top; 65 for(i=0;i<cz;i++) 66 { 67 T::ins(c[i].x,rt2);rtt[c[i].L]=rt2; 68 } 69 for(i=0;i<qz;i++) 70 { 71 if(q[i].l<=l&&r<=q[i].r) 72 { 73 rt1=(--rtt.upper_bound(q[i].L-1))->second; 74 rt2=(--rtt.upper_bound(q[i].R))->second; 75 ans[q[i].num]=max(ans[q[i].num],T::que(q[i].x,rt1,rt2)); 76 } 77 } 78 T::top=tmem; 79 if(l==r) return; 80 int mid=l+(r-l)/2;vector<Q> q1,q2,c1,c2; 81 for(i=0;i<qz;i++) 82 { 83 if(!(q[i].l<=l&&r<=q[i].r)) 84 { 85 if(q[i].l<=mid) q1.pb(q[i]); 86 if(mid<q[i].r) q2.pb(q[i]); 87 } 88 } 89 for(i=0;i<cz;i++) 90 { 91 if(c[i].l<=mid) c1.pb(c[i]); 92 else c2.pb(c[i]); 93 } 94 solve(q1,c1,l,mid); 95 solve(q2,c2,mid+1,r); 96 } 97 bool type[100100]; 98 int main() 99 { 100 int i,t,a,b,c,d,idx,dd=1; 101 T::init(); 102 scanf("%d%d",&n,&m); 103 for(i=1;i<=n;i++) 104 { 105 scanf("%d",&t); 106 rt[i]=rt[i-1];T::ins(t,rt[i]); 107 } 108 for(i=1;i<=m;i++) 109 { 110 scanf("%d",&idx); 111 if(idx==0) 112 { 113 scanf("%d%d",&a,&b); 114 qq1.pb((Q){0,a,0,b,++dd,0,i}); 115 } 116 else 117 { 118 type[i]=1; 119 scanf("%d%d%d%d",&a,&b,&c,&d); 120 ans[i]=T::que(c,rt[a-1],rt[b]); 121 if(d!=0) qq0.pb((Q){1,a,b,c,max(1,dd-d+1),dd,i}); 122 } 123 } 124 sort(qq1.begin(),qq1.end(),c1); 125 solve(qq0,qq1,1,dd); 126 for(i=1;i<=m;i++) 127 if(type[i]) 128 printf("%d\n",ans[i]); 129 return 0; 130 }
以上是关于洛谷 P4585 [FJOI2015]火星商店问题的主要内容,如果未能解决你的问题,请参考以下文章