• 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 }
  • 相关阅读:
    FreeIPA部署及基本使用
    第7天:Django模板使用与表单
    第6天:数据库配置与模型
    第5天:基于类的视图与中间件
    linux下修改MySQL表名与表的字符编码
    webService理解(一)
    查询MySQL库下所有表名,数据为空的表名
    linux中MySQL连接找不到mysql.sock文件
    初步书写Webservice项目,运行后报错:Cannot assign requested address: bind
    linux配置jdk,MySQL环境
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9014194.html
Copyright © 2020-2023  润新知