[BZOJ4137]火星商店问题

Description

火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店。商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价。每个商店每天都有可能进一些新商品,其标价可能与已有商品相同。 
火星人在这条商业街购物时,通常会逛这条商业街某一段路上的所有商店,譬如说商店编号在区间[L,R]中的商店,从中挑选1件自己最喜欢的商品。每个火星人对商品的喜好标准各不相同。通常每个火星人都有一个自己的喜好密码x。对每种标价为val的商品,喜好密码为x的火星人对这种商品的喜好程度与val异或x的值成正比。也就是说,val xor x的值越大,他就越喜欢该商品。每个火星人的购物卡在所有商店中只能购买最近d天内(含当天)进货的商品。另外,每个商店都有一种特殊商品不受进货日期限制,每位火星人在任何时刻都可以选择该特殊商品。每个商店中每种商品都能保证供应,不存在商品缺货的问题。 
对于给定的按时间顺序排列的事件,计算每个购物的火星人的在本次购物活动中最喜欢的商品,即输出val xor x的最大值。这里所说的按时间顺序排列的事件是指以下2种事件: 
事件0,用三个整数0,s,v,表示编号为s的商店在当日新进一种标价为v 的商品。 
事件1,用5个整数1,L,R,x,d,表示一位火星人当日在编号为L到R的商店购买d天内的商品,该火星人的喜好密码为x。

Input

第1行中给出2个正整数n,m,分别表示商店总数和事件总数。 
第2行中有n个整数,第i个整数表示商店i的特殊商品标价。 
接下来的m行,每行表示1个事件。每天的事件按照先事件0,后事件1的顺序排列。 

Output

将计算出的每个事件1的val xor x的最大值依次输出。

Sample Input

4 6
1 2 3 4
1 1 4 1 0
0 1 4
0 1 3
1 1 1 1 0
1 1 1 1 1
1 1 2 1 2

Sample Output

5
0
2
5

HINT

n, m <= 100000
数据中,价格不大于100000

Source

显然呢这道题可以用线段树套可持久化$Trie$来实现,不过不是我们讨论的范围
我们考虑每个修改对询问的影响是一段区间
按时间建立线段树,那么每个询问对应了线段树不超过$logn$个节点,每次修改对应着从该时间点到根节点的路径
所以每个修改对$logn$个节点有贡献,因此我们在回答每个节点的询问前,直接暴力把对该节点有影响的修改插进线段树即可
因为询问被拆成了许多线段树节点,于是要对这些被拆的询问取$max$
代码:
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstring>
  6 #define M 100010
  7 #define ls node<<1
  8 #define rs node<<1|1
  9 using namespace std;
 10 
 11 int n,m,cnt,cnt1,cnt2;
 12 int rt[M],f[M],ans[M];
 13 vector<int>seg[M<<2];
 14 struct CG{int s,v,t;}q[M],tmp1[M],tmp2[M];
 15 struct ASK{int l,r,l1,r1,x;}p[M];
 16 bool cmp(CG a1,CG a2) {return a1.s<a2.s;}
 17 
 18 struct Trie
 19 {
 20     int cnt;
 21     int val[M<<5],ch[M<<5][2];
 22     void insert(int &now,int pre,int w,int o)
 23     {
 24         
 25         now=++cnt,val[now]=val[pre]+1;
 26         ch[now][0]=ch[pre][0];ch[now][1]=ch[pre][1];
 27         if(o==-1) return;bool c=w&(1<<o);
 28         insert(ch[now][c],ch[pre][c],w,o-1);
 29     }
 30     int query(int now,int pre,int w,int o)
 31     {
 32         if(o==-1) return 0;
 33         bool c=w&(1<<o);
 34         int tmp=val[ch[now][c^1]]-val[ch[pre][c^1]];
 35         if(tmp) return query(ch[now][c^1],ch[pre][c^1],w,o-1)+(1<<o);
 36         else return query(ch[now][c],ch[pre][c],w,o-1);
 37     }
 38 }T;
 39 
 40 void insert(int node,int l,int r,int l1,int r1,int id)
 41 {
 42     if(l1>r1) return;
 43     if(l1<=l&&r1>=r) {seg[node].push_back(id);return;}
 44     int mid=(l+r)/2;
 45     if(l1<=mid) insert(ls,l,mid,l1,r1,id);
 46     if(r1>mid) insert(rs,mid+1,r,l1,r1,id);
 47 }
 48 
 49 int get(int v)
 50 {
 51     int l=1,r=cnt,ans=0;
 52     while(l<=r)
 53     {
 54         int mid=(l+r)/2;
 55         if(f[mid]<=v) ans=mid,l=mid+1;
 56         else r=mid-1;
 57     }
 58     return ans;
 59 }
 60 
 61 void cal(int node,int l,int r)
 62 {
 63     cnt=T.cnt=0;
 64     for(int i=l;i<=r;i++)
 65     {
 66         f[++cnt]=q[i].s;
 67         T.insert(rt[cnt],rt[cnt-1],q[i].v,17);
 68     }
 69     for(int i=0;i<seg[node].size();i++)
 70     {
 71         int id=seg[node][i];
 72         int l=get(p[id].l-1);
 73         int r=get(p[id].r);
 74         ans[id]=max(ans[id],T.query(rt[r],rt[l],p[id].x,17));
 75     }
 76 }
 77 
 78 void solve(int node,int l,int r,int l1,int r1)
 79 {
 80     if(l1>r1) return;
 81     cal(node,l,r);
 82     if(l==r) return;
 83     int mid=(l+r)/2,t1=0,t2=0;
 84     for(int i=l1;i<=r1;i++)
 85     {
 86         if(q[i].t<=mid) tmp1[++t1]=q[i];
 87         else tmp2[++t2]=q[i];
 88     }
 89     for(int i=1;i<=t1;i++) q[i+l1-1]=tmp1[i];
 90     for(int i=1;i<=t2;i++) q[i+l1-1+t1]=tmp2[i];
 91     solve(ls,l,mid,l1,l1+t1-1);
 92     solve(rs,mid+1,r,l1+t1,r1);
 93 }
 94 
 95 int main()
 96 {
 97     scanf("%d%d",&n,&m);
 98     for(int i=1;i<=n;i++) 
 99     {
100         int x;scanf("%d",&x);
101         T.insert(rt[i],rt[i-1],x,17);
102     }
103     for(int i=1;i<=m;i++)
104     {
105         int opt;scanf("%d",&opt);
106         if(!opt)
107         {
108             int s,v;scanf("%d%d",&s,&v);
109             cnt1++;q[cnt1]=(CG){s,v,cnt1};
110         }
111         else
112         {
113             int l,r,x,d;scanf("%d%d%d%d",&l,&r,&x,&d);
114             ans[++cnt2]=T.query(rt[r],rt[l-1],x,17);
115             p[cnt2]=(ASK){l,r,max(1,cnt1-d+1),cnt1,x};
116         }
117     }
118     for(int i=1;i<=cnt2;i++) 
119         insert(1,1,cnt1,p[i].l1,p[i].r1,i);
120     sort(q+1,q+1+cnt1,cmp);
121     solve(1,1,cnt1,1,cnt1);
122     for(int i=1;i<=cnt2;i++) printf("%d\n",ans[i]);
123     return 0;
124 }

 

 

posted @ 2018-11-24 11:47  Slr  阅读(198)  评论(0编辑  收藏  举报