Xors on Segments Codeforces - 620F
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的更多相关文章
- Codeforces 620F Xors on Segments(暴力+DP)
题目链接 Xors on Segments 预处理出$x[i]$ $=$ $1$ $xor$ $2$ $xor$ $3$ $xor$ $……$ $xor$ $i$ 话说这题$O(n^{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 ...
- D - Nested Segments CodeForces - 652D (离散化+树桩数组)
D - Nested Segments CodeForces - 652D You are given n segments on a line. There are no ends of some ...
- codeforces 620F. Xors on Segments
题目链接 定义一种操作f(u, v) = u^u+1^.......^v. (u<=v), 给n个数, q个询问, 每个询问给出一个区间[l, r], 求这个区间里的f(a[i], a[j]) ...
- Segments CodeForces 909B (找规律)
Description You are given an integer N. Consider all possible segments (线段,划分)on the coordinate axis ...
- A - Points and Segments CodeForces - 429E
题解: 方法非常巧妙的一道题 首先考虑要求全部为0怎么做 发现是个欧拉回路的问题(很巧妙) 直接dfs一遍就可以了 而这道题 要求是-1,1,0 我们可以先离散化 完了之后判断每个点被奇数还是偶数条边 ...
- Bipartite Segments CodeForces - 901C (区间二分图计数)
大意: 给定无向图, 无偶环, 每次询问求[l,r]区间内, 有多少子区间是二分图. 无偶环等价于奇环仙人掌森林, 可以直接tarjan求出所有环, 然后就可以预处理出每个点为右端点时的答案. 这样的 ...
- Four Segments CodeForces - 846C
题目 题意:sum(l,r)表示数列a中索引为l到r-1(都包含)的数之和(如果l==r则为0).给出数列a,求合适的delim0, delim1, delim2,使res = sum(0, deli ...
- Educational Codeforces Round 6
620A - Professor GukiZ's Robot 20171122 \(ans=max(\left | x2-x1 \right |,\left | y2-y1 \right |)\ ...
随机推荐
- Web容器自己主动对HTTP请求中參数进行URLDecode处理
这篇文章转载自 : Web容器自己主动对HTTP请求中參数进行URLDecode处理 如题.在Java中或许非常多人都没有注意到当我们发送一个http请求时,假设附带的參数被URLEncode之后,到 ...
- [PythonCode]扫描局域网的alive ip地址
内网的主机都是自己主动分配ip地址,有时候须要查看下有那些ip在使用,就写了个简单的脚本. linux和windows下都能够用,用多线程来ping1-255全部的地址,效率不高.2分钟左右. 先凑合 ...
- Data obtained from ping: is it round trip or one way?
I have 2 servers, each in two separate locations. I need to host an application on one, and the data ...
- win8系统 重装系统如何删除EFI分区
在PE下(一般重装系统就是在PE下),依次输入如下命令(注意虽然显示的是中文名"磁盘0",但是还是用英文disk 0) list disk select disk 0 clean
- 【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取
在入门系列的教程中.我们经常使用 d3.json() 函数来读取 json 格式的文件.json 格式非常强大.但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 O ...
- OpenCV---在图片上加入文字
/****************************************** func:cvText desc:put text on an image @param img The ima ...
- eclipse maven 插件的安装和配置
maven3 安装: 安装 Maven 之前要求先确定你的 JDK 已经安装配置完毕.Maven是 Apache 下的一个项目.眼下最新版本号是 3.0.4.我用的也是这个. 首先去官网下载 Mave ...
- windows下的两个等待函数
windows下的两个等待技术 第一种: Win32 Sleep()函数 这个函数要求操作系统中止线程动作.直到读过某个指定的时间之后才恢复.能在某个线程结束时(而不是某段时间结束时)被调 ...
- Codeforces 104C Cthulhu dfs暴力 || 点双连通缩点
题目链接:点击打开链接 题意: 给定n个点m条边的无向图 问图中是否存在 有且仅有一个简单环和一些树,且这些树的root都在这个简单环上. 瞎写了个点双. . == #include <stdi ...
- css3最新版中文参考手册在线浏览
对于CSS 3.0,它对于我们Web设计人员来说不只是新奇的技术,更重要的是这些全新概念的Web应用给我们的设计开发提高了效率以及更多的无限可能性,我们将不必再依赖图片或者 Javascript 去完 ...