1. 程式人生 > >洛谷 P4585 [FJOI2015]火星商店問題

洛谷 P4585 [FJOI2015]火星商店問題

空間 target tar init namespace IE urn 曾經 turn

(勿看,僅作筆記)

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]火星商店問題