zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
    123     return 0;
    124 }
  • 相关阅读:
    恢复计算机崩溃数据的五款最佳Linux发行版
    不敢想象!Vim使用者的“大脑”竟是这样
    开发者和系统管理者最喜爱的开源工具Vim 起步学习的五个技巧
    .NET程序与CA对接一直提示重定向
    覆盖原有div或者Input的鼠标移上去描述
    IOS9以上如何导入铃声并设置
    c# 动态调用webserver
    没有终结点在侦听可以接受消息的*这通常是由于不正确的地址或者 SOAP操作导致的
    url 参数的加号变成空格处理
    在git 服务器挂载、创建新的项目、克隆新的项目
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10011529.html
Copyright © 2011-2022 走看看