zoukankan      html  css  js  c++  java
  • Xors on Segments Codeforces

    http://codeforces.com/problemset/problem/620/F

    此题是莫队,但是不能用一般的莫队做,因为是最优化问题,没有办法在删除元素的时候维护答案。


    这题的方法(好像还有个名字叫"回滚莫队“,说明:https://blog.csdn.net/maverickfw/article/details/72988286):

    官方题解:http://codeforces.com/blog/entry/22936

    设完成一次"加入贡献"的操作的复杂度是O(p)

    首先定块大小sz,定每个坐标应该属于的块。

    对于左右端点在同一块内的询问,暴力处理即可。每一个询问需要复杂度O(p*sz)

    对于其他询问,按左端点所属的块分类。

    分类完后,对于同一类的询问,按右端点从小到大排序。对于每一类的询问分开处理。

    对于每一类,先把"当前维护区间"的左端点定为 属于该块的坐标 中最靠右的坐标(这样的话,该类询问的左端点都小于等于这个点且离这个点距离不超过sz),右端点定为左端点-1(为了让区间为空)。还要清空当前答案。

    对于该类中每一个询问,先照常移动右端点到与询问的右端点相同,然后记下此时的答案,然后把左端点移动到与询问的左端点相同,得到该询问的答案并记录;然后把左端点的移动还原,把答案还原即可(这样就避开了维护答案)

    对于每一类,右端点最多有O(n)次移动,而有n/sz类,这一部分复杂度是O(p*n*n/sz);对于每一个询问,额外还要O(p*sz)的复杂度进行左端点的调整

    因此,总复杂度是O(p*(n*n/sz+m*sz)),当sz=sqrt(n*n/m)时最小


    解决了莫队的问题,还要解决异或最大值维护的问题。这个是用01字典树做的,就不写了。。。看官方题解吧

    (大概要支持在01字典树中查询:集合中,对于所有"第二权值"小于等于/大于等于特定值的元素,查询与另一给定值异或的最大值,挺奇怪的)

    错误记录:

    1.trie没有开垃圾回收,内存不够

    2.计算块大小时,没有注意块大小可能变成0

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cmath>
      4 #include<set>
      5 #include<queue>
      6 #include<vector>
      7 using namespace std;
      8 int f[2000100];
      9 int n,m,sz,sz1;
     10 //int ttt;
     11 int lft[40];
     12 namespace Trie
     13 {
     14 const int l2n=20;
     15 int sz[4000100],ch[4000100][2],dat[4000100];
     16 multiset<int> ss[4001000];
     17 int x,kkk;
     18 queue<int> qqq;
     19 int getnode()
     20 {
     21     //yttt=max(ttt,int(2000100-qqq.size()));
     22     int t=qqq.front();qqq.pop();
     23     return t;
     24 }
     25 void delnode(int x)
     26 {
     27     qqq.push(x);
     28 }
     29 void deltree(int x)
     30 {
     31     if(!x)    return;
     32     deltree(ch[x][0]);
     33     deltree(ch[x][1]);
     34     ss[x].clear();ch[x][0]=ch[x][1]=dat[x]=sz[x]=0;
     35     delnode(x);
     36 }
     37 void init()
     38 {
     39     int i;
     40     for(i=1;i<4000100;i++)    qqq.push(i);
     41     lft[0]=1;
     42     for(i=1;i<=l2n;i++)    lft[i]=lft[i-1]<<1;
     43 }
     44 int getdat1(int x)    {return x?dat[x]:0x3f3f3f3f;}
     45 void _ins1(int p,int &num)
     46 {
     47     if(!num)    num=getnode(),dat[num]=0x3f3f3f3f;
     48     sz[num]++;
     49     if(p>=0)    _ins1(p-1,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][0]),getdat1(ch[num][1]));
     50     else    ss[num].insert(kkk),dat[num]=*ss[num].begin();
     51 }
     52 void ins1(int d,int kk,int &num)    {x=d;kkk=kk;_ins1(l2n-1,num);}
     53 //ins1维护插入kk的最小值
     54 void _ins2(int p,int &num)
     55 {
     56     if(!num)    num=getnode();
     57     sz[num]++;
     58     if(p>=0)    _ins2(p-1,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][0]],dat[ch[num][1]]);
     59     else    ss[num].insert(kkk),dat[num]=*ss[num].rbegin();
     60 }
     61 void ins2(int d,int kk,int &num)    {x=d;kkk=kk;_ins2(l2n-1,num);}
     62 //ins2维护插入kk的最大值
     63 
     64 
     65 void _era1(int p,int &num)
     66 {
     67     sz[num]--;
     68     if(p>=0)    _era1(p-1,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][0]),getdat1(ch[num][1]));
     69     else    ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?0x3f3f3f3f:*ss[num].begin();
     70 }
     71 void era1(int d,int kk,int &num)    {x=d;kkk=kk;_era1(l2n-1,num);}
     72 void _era2(int p,int &num)
     73 {
     74     sz[num]--;
     75     if(p>=0)    _era2(p-1,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][0]],dat[ch[num][1]]);
     76     else    ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?0:*ss[num].rbegin();
     77 }
     78 void era2(int d,int kk,int &num)    {x=d;kkk=kk;_era2(l2n-1,num);}
     79 
     80 
     81 int que1(int x,int kk,int num)//que1查询维护值小于等于kk的数中与x的xor最大值
     82 {
     83     int ans=0,i;bool t;
     84     for(i=l2n-1;i>=0;--i)
     85     {
     86         t=x&lft[i];
     87         if(sz[ch[num][!t]]&&dat[ch[num][!t]]<=kk)    ans|=lft[i],num=ch[num][!t];
     88         else    num=ch[num][t];
     89     }
     90     return ans;
     91 }
     92 int que2(int x,int kk,int num)//que2查询维护值大于等于kk的数中与x的xor最大值
     93 {
     94     int ans=0,i;bool t;
     95     for(i=l2n-1;i>=0;--i)
     96     {
     97         t=x&lft[i];
     98         if(sz[ch[num][!t]]&&dat[ch[num][!t]]>=kk)    ans|=lft[i],num=ch[num][!t];
     99         else    num=ch[num][t];
    100     }
    101     return ans;
    102 }
    103 }
    104 using Trie::ins1;using Trie::ins2;
    105 using Trie::era1;using Trie::era2;
    106 using Trie::que1;using Trie::que2;
    107 using Trie::deltree;
    108 struct Q
    109 {
    110     int l,r,num;
    111     Q(){}
    112     Q(int a,int b,int c):l(a),r(b),num(c){}
    113 };
    114 int a[50100],ans[5010];
    115 int rt1,rt2;
    116 int anss;
    117 void add1(int p)//加入p的贡献
    118 {
    119     ins1(f[p-1],p,rt1);ins2(f[p],p,rt2);
    120     anss=max(anss,que1(f[p],p,rt1));
    121     //printf("a%d
    ",f[p]^f[p-1]);
    122     anss=max(anss,que2(f[p-1],p,rt2));
    123 }
    124 void del1(int p)
    125 {
    126     era1(f[p-1],p,rt1);era2(f[p],p,rt2);
    127 }
    128 vector<Q> q[1010];
    129 bool cmp(const Q &a,const Q &b)    {return a.r<b.r;}
    130 int main()
    131 {
    132     int i,j,j2,l,r,tans;Trie::init();
    133     for(i=1;i<=2000000;i++)    f[i]=f[i-1]^i;
    134     scanf("%d%d",&n,&m);sz=max(1,int(sqrt(double(n)/m*n)));sz1=(n-1)/sz;
    135     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    136     for(i=1;i<=m;i++)
    137     {
    138         scanf("%d%d",&l,&r);
    139         if((l-1)/sz==(r-1)/sz)
    140         {
    141             deltree(rt1);deltree(rt2);
    142             rt1=rt2=anss=0;
    143             for(j=l;j<=r;j++)    add1(a[j]);
    144             ans[i]=anss;
    145             //printf("a%d %d
    ",i,ans[i]);
    146         }
    147         else
    148             q[(l-1)/sz].push_back(Q(l,r,i));
    149     }
    150     for(i=0;i<=sz1;i++)
    151     {
    152         sort(q[i].begin(),q[i].end(),cmp);
    153         l=(i+1)*sz;r=l-1;rt1=rt2=anss=0;
    154         for(j=0;j<q[i].size();j++)
    155         {
    156             while(r<q[i][j].r)    add1(a[++r]);
    157             tans=anss;
    158             for(j2=l-1;j2>=q[i][j].l;j2--)    add1(a[j2]);
    159             ans[q[i][j].num]=anss;
    160             for(j2=l-1;j2>=q[i][j].l;j2--)    del1(a[j2]);
    161             anss=tans;
    162         }
    163         deltree(rt1);deltree(rt2);
    164     }
    165     for(i=1;i<=m;i++)    printf("%d
    ",ans[i]);
    166     //printf("a%d
    ",ttt);
    167     return 0;
    168 }
  • 相关阅读:
    call()与apply()的作用与区别
    Tomcat8/9的catalina.out中文乱码问题解决
    怎样查看Jenkins的版本
    每日日报2020.8.18
    528. Random Pick with Weight
    875. Koko Eating Bananas
    721. Accounts Merge
    515. Find Largest Value in Each Tree Row
    286. Walls and Gates (Solution 1)
    408. Valid Word Abbreviation
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9014194.html
Copyright © 2011-2022 走看看