zoukankan      html  css  js  c++  java
  • 洛谷 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
    ",ans[i]);
    129     return 0;
    130 }
  • 相关阅读:
    判断一个字符串是否为回文串
    读<大道至简>软件工程实践者的思想有感
    Java学习10.23(设置页面的编码方式1)
    Java学习10.25(javaweb在界面输出2)
    【搜索】C000_LG_奶酪(bfs)
    【并查集】B001_AW_自动程序分析(不要求顺序时的离散化)
    b_aw_信息传递 & 银河英雄传说(并查集暴力求环 / 记忆化 | 带权并查集)
    b_pat_团伙头目(并查集/dfs+字符串整形互相映射)
    【堆】C003_AW_接水问题(暴力 / 堆)
    【并查集】C002_AW_樱桃网 & 打击犯罪(最下生成树 / dfs / 并查集求连通块)
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9034574.html
Copyright © 2011-2022 走看看