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

 #include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
using namespace std;
int f[];
int n,m,sz,sz1;
//int ttt;
int lft[];
namespace Trie
{
const int l2n=;
int sz[],ch[][],dat[];
multiset<int> ss[];
int x,kkk;
queue<int> qqq;
int getnode()
{
//yttt=max(ttt,int(2000100-qqq.size()));
int t=qqq.front();qqq.pop();
return t;
}
void delnode(int x)
{
qqq.push(x);
}
void deltree(int x)
{
if(!x) return;
deltree(ch[x][]);
deltree(ch[x][]);
ss[x].clear();ch[x][]=ch[x][]=dat[x]=sz[x]=;
delnode(x);
}
void init()
{
int i;
for(i=;i<;i++) qqq.push(i);
lft[]=;
for(i=;i<=l2n;i++) lft[i]=lft[i-]<<;
}
int getdat1(int x) {return x?dat[x]:0x3f3f3f3f;}
void _ins1(int p,int &num)
{
if(!num) num=getnode(),dat[num]=0x3f3f3f3f;
sz[num]++;
if(p>=) _ins1(p-,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][]),getdat1(ch[num][]));
else ss[num].insert(kkk),dat[num]=*ss[num].begin();
}
void ins1(int d,int kk,int &num) {x=d;kkk=kk;_ins1(l2n-,num);}
//ins1维护插入kk的最小值
void _ins2(int p,int &num)
{
if(!num) num=getnode();
sz[num]++;
if(p>=) _ins2(p-,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][]],dat[ch[num][]]);
else ss[num].insert(kkk),dat[num]=*ss[num].rbegin();
}
void ins2(int d,int kk,int &num) {x=d;kkk=kk;_ins2(l2n-,num);}
//ins2维护插入kk的最大值 void _era1(int p,int &num)
{
sz[num]--;
if(p>=) _era1(p-,ch[num][!!(x&lft[p])]),dat[num]=min(getdat1(ch[num][]),getdat1(ch[num][]));
else ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?0x3f3f3f3f:*ss[num].begin();
}
void era1(int d,int kk,int &num) {x=d;kkk=kk;_era1(l2n-,num);}
void _era2(int p,int &num)
{
sz[num]--;
if(p>=) _era2(p-,ch[num][!!(x&lft[p])]),dat[num]=max(dat[ch[num][]],dat[ch[num][]]);
else ss[num].erase(ss[num].find(kkk)),dat[num]=ss[num].empty()?:*ss[num].rbegin();
}
void era2(int d,int kk,int &num) {x=d;kkk=kk;_era2(l2n-,num);} int que1(int x,int kk,int num)//que1查询维护值小于等于kk的数中与x的xor最大值
{
int ans=,i;bool t;
for(i=l2n-;i>=;--i)
{
t=x&lft[i];
if(sz[ch[num][!t]]&&dat[ch[num][!t]]<=kk) ans|=lft[i],num=ch[num][!t];
else num=ch[num][t];
}
return ans;
}
int que2(int x,int kk,int num)//que2查询维护值大于等于kk的数中与x的xor最大值
{
int ans=,i;bool t;
for(i=l2n-;i>=;--i)
{
t=x&lft[i];
if(sz[ch[num][!t]]&&dat[ch[num][!t]]>=kk) ans|=lft[i],num=ch[num][!t];
else num=ch[num][t];
}
return ans;
}
}
using Trie::ins1;using Trie::ins2;
using Trie::era1;using Trie::era2;
using Trie::que1;using Trie::que2;
using Trie::deltree;
struct Q
{
int l,r,num;
Q(){}
Q(int a,int b,int c):l(a),r(b),num(c){}
};
int a[],ans[];
int rt1,rt2;
int anss;
void add1(int p)//加入p的贡献
{
ins1(f[p-],p,rt1);ins2(f[p],p,rt2);
anss=max(anss,que1(f[p],p,rt1));
//printf("a%d\n",f[p]^f[p-1]);
anss=max(anss,que2(f[p-],p,rt2));
}
void del1(int p)
{
era1(f[p-],p,rt1);era2(f[p],p,rt2);
}
vector<Q> q[];
bool cmp(const Q &a,const Q &b) {return a.r<b.r;}
int main()
{
int i,j,j2,l,r,tans;Trie::init();
for(i=;i<=;i++) f[i]=f[i-]^i;
scanf("%d%d",&n,&m);sz=max(,int(sqrt(double(n)/m*n)));sz1=(n-)/sz;
for(i=;i<=n;i++) scanf("%d",&a[i]);
for(i=;i<=m;i++)
{
scanf("%d%d",&l,&r);
if((l-)/sz==(r-)/sz)
{
deltree(rt1);deltree(rt2);
rt1=rt2=anss=;
for(j=l;j<=r;j++) add1(a[j]);
ans[i]=anss;
//printf("a%d %d\n",i,ans[i]);
}
else
q[(l-)/sz].push_back(Q(l,r,i));
}
for(i=;i<=sz1;i++)
{
sort(q[i].begin(),q[i].end(),cmp);
l=(i+)*sz;r=l-;rt1=rt2=anss=;
for(j=;j<q[i].size();j++)
{
while(r<q[i][j].r) add1(a[++r]);
tans=anss;
for(j2=l-;j2>=q[i][j].l;j2--) add1(a[j2]);
ans[q[i][j].num]=anss;
for(j2=l-;j2>=q[i][j].l;j2--) del1(a[j2]);
anss=tans;
}
deltree(rt1);deltree(rt2);
}
for(i=;i<=m;i++) printf("%d\n",ans[i]);
//printf("a%d\n",ttt);
return ;
}

Xors on Segments Codeforces - 620F的更多相关文章

  1. Codeforces 620F Xors on Segments(暴力+DP)

    题目链接 Xors on Segments 预处理出$x[i]$ $=$ $1$ $xor$ $2$ $xor$ $3$ $xor$ $……$ $xor$ $i$ 话说这题$O(n^{2})$居然能过 ...

  2. Educational Codeforces Round 6 F. Xors on Segments 暴力

    F. Xors on Segments 题目连接: http://www.codeforces.com/contest/620/problem/F Description You are given ...

  3. D - Nested Segments CodeForces - 652D (离散化+树桩数组)

    D - Nested Segments CodeForces - 652D You are given n segments on a line. There are no ends of some ...

  4. codeforces 620F. Xors on Segments

    题目链接 定义一种操作f(u, v) = u^u+1^.......^v. (u<=v), 给n个数, q个询问, 每个询问给出一个区间[l, r], 求这个区间里的f(a[i], a[j]) ...

  5. Segments CodeForces 909B (找规律)

    Description You are given an integer N. Consider all possible segments (线段,划分)on the coordinate axis ...

  6. A - Points and Segments CodeForces - 429E

    题解: 方法非常巧妙的一道题 首先考虑要求全部为0怎么做 发现是个欧拉回路的问题(很巧妙) 直接dfs一遍就可以了 而这道题 要求是-1,1,0 我们可以先离散化 完了之后判断每个点被奇数还是偶数条边 ...

  7. Bipartite Segments CodeForces - 901C (区间二分图计数)

    大意: 给定无向图, 无偶环, 每次询问求[l,r]区间内, 有多少子区间是二分图. 无偶环等价于奇环仙人掌森林, 可以直接tarjan求出所有环, 然后就可以预处理出每个点为右端点时的答案. 这样的 ...

  8. Four Segments CodeForces - 846C

    题目 题意:sum(l,r)表示数列a中索引为l到r-1(都包含)的数之和(如果l==r则为0).给出数列a,求合适的delim0, delim1, delim2,使res = sum(0, deli ...

  9. Educational Codeforces Round 6

    620A - Professor GukiZ's Robot    20171122 \(ans=max(\left | x2-x1 \right |,\left | y2-y1 \right |)\ ...

随机推荐

  1. java 返回json数据

    Student st1 = new Student(1, "dg", 18, new Date());            Student st2 = new Student(2 ...

  2. Mysql不同存储引擎的表转换方法

    Mysql不同存储引擎的表转换方法 1.Alter table直接修改表的存储引擎,但是这样会导致大量的系统开销,Mysql为此要执行一个就表向新表的逐行复制.在此期间,转换操作可能会占用服务器的所有 ...

  3. 【c++】c++一些基础面试题

    http://www.mianwww.com/html/2013/10/19128.html http://blog.csdn.net/wdzxl198/article/details/9050751 ...

  4. sql跟踪及tkprof使用

    简述 在oracle数据库中,awr是关于数据库系统总体的负载情况和运行情况的报告.而当系统负载都显示正常,而client运行某些动作响应非常慢,或者某些终端连接的会话运行缓慢或异常时,就须要用到会话 ...

  5. 【Mongodb教程 第十一课 】MongoDB 聚合

    聚合操作过程中的数据记录和计算结果返回.聚合操作分组值从多个文档,并可以执行各种操作,分组数据返回单个结果.在SQL COUNT(*)和group by 相当于MongoDB的聚集. aggregat ...

  6. 【JS】JavaScript引擎的内部执行机制

     近期在复习JavaScript,看到setTimeout函数时.想起曾经刚学时,在一本书上看过setTimeout()里的回调函数执行的间隔时间有昌不是后面设置的值.曾经没想太多.网上看了JS大 ...

  7. 论持久战之PHPStorm Xdebug Remote 调试环境搭建(不依赖本地环境)

    最近公司自己搭建了一个资源管理平台,哈哈,当然是我在github上找的,后台用PHP开发.个人觉得写得非常nice,web页面几乎模拟了真实OS,有兴趣的朋友下载部署体验https://github. ...

  8. mysql16---读写分离

    读写分离(负载平衡)(读写分离肯定要用到主从复制) 如果数据库压力很大,一台机器支撑不了,那么可以用mysql复制实现多台机器同步,将数据库的压力分散. 分表不能解决并发量大的问题. Sql语句发过来 ...

  9. POJ2594 Treasure Exploratio —— 最小路径覆盖 + 传递闭包

    题目链接:https://vjudge.net/problem/POJ-2594 Treasure Exploration Time Limit: 6000MS   Memory Limit: 655 ...

  10. 计算机学院大学生程序设计竞赛(2015’11)1005 ACM组队安排

    1005 ACM组队安排 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Pro ...