洛谷 P4585 [FJOI2015]火星商店问题

(勿看,仅作笔记)

bzoj权限题。。。

https://www.luogu.org/problemnew/show/P4585

对于特殊商品,直接可持久化trie处理一下即可

剩下的,想了一段时间cdq,但是没想出来。。。应该是不行的

事实上,如果询问的不是最大值,而是一些满足[l,r]的答案等于[1,r]的答案-[1,l-1]的答案的东西,那么的确可以每个询问拆成两个直接cdq。。。

但是这题就不能。。不过可以线段树分治,这是基于[l,r]的答案可以被分成多个线段树上区间(这些区间的并等于[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 }

 

posted @ 2018-05-14 09:32  hehe_54321  阅读(265)  评论(0编辑  收藏  举报
AmazingCounters.com