题目描述
Description
法法塔和wyl8899都喜欢玩游戏。但是每次玩游戏法法塔都被wyl8899虐。
为了安慰可怜的法法塔,wyl8899决定大发慈悲,修改了一下游戏规则。
是这样的,这儿有一堆石子排成一列,每次wyl8899让hza选择一个区间进行游戏。游戏嘛,就是采用最普通的规则:两人轮流操作,每次选择一堆石子,取掉不为0的石子数,没法操作者失败。法法塔要做的是这样的:
我们现在定义一个区间的弱菜值:表示如果法法塔先取石子,而且法法塔第一步取的石子规定是最右边的那堆的话,为了必胜,第一步需要取的石子数。如果没法获胜的话,那么弱菜值就是-1。
法法塔要选择一个区间[l,r],使得r为wyl8899给定的某个数,l属于[a,b],a,b也是wyl8899给定的,要求这个区间的弱菜值是满足前面的条件中最大。请给出这个最大的弱菜值。
如果最大弱菜值不为-1,法法塔就会马上取走该区间最右端的石子堆最大弱菜值数量的石子。
Input
第一行一个正整数n,描述了石子的堆数,接下来一行n个数,描述每堆石子的数目。
接下来一行m,表示将进行要进行m次游戏,每次游戏由三个值刻画,r,a,b。r表示被选定的右端点,[a,b]表示选择的区间的左端点的范围
Output
对于每个询问输出最大的弱菜值。
Sample Input
输入1:
12
662 477 125 483 17 560 232 59 176 928 807 659
5
5 2 5
4 4 4
2 1 2
6 4 6
6 2 3
输入2:
7
230 883 456 1020 966 899 610
2
7 1 2
2 1 2
输入3:
11
392 808 14 71 393 79 11 74 713 232 142
5
8 3 8
9 5 9
3 1 1
8 2 8
7 4 6
Sample Output
输出1:
17
483
477
560
-1
输出2:
352
883
输出3:
74
713
-1
-1
-1
Data Constraint
n<=100000,m<=10000,每堆的石子数<=1000。
题解
口胡警告
O3警告
题解的做法是把n分块,每个块建可持久化trie
每次修改就对整块打标记,对散块暴力
查找就尽量往小的找(因为这样剩下的才能尽量小)
时间复杂度:O(m*√n*logS)
下面是自己在考场上想到的sb做法
建1024棵权值线段树,每棵线段树对应一种异或后缀的出现位置
查找就暴力枚举判断对应区间内是否存在某个后缀
修改就相当于第R位改变的位置(设其对应的二进制为s)在1~R的异或后缀取反,等于把第i棵树和第i^s棵树的1~R区间交换
时间复杂度:O(m*1024*logn)
因为题解的复杂度写错了所以其实这样做更慢
code
因为是自己乱写的所以不删注释了
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define low(x) (x&(-(x)))
using namespace std;
int a[100001];
int tr[10000001][3];
int Tr[100001];
char s1[1400001];
int Q,n,i,j,k,l,Find,ans,R,A,B,s,len,I;
bool bz;
char *Ch=s1;
int getint()
{
register int x=0;
while (*Ch<'0' || *Ch>'9') *++Ch;
while (*Ch>='0' && *Ch<='9') x=x*10+(*Ch-'0'),*++Ch;
return x;
}
void swap(int &x,int &y)
{
int z=x;
x=y;
y=z;
}
void New(int t,int x)
{
if (!tr[t][x])
tr[t][x]=++len;
}
void CHANGE(register int t,int s)
{
while (t<=n)
{
Tr[t]^=s;
t+=low(t);
}
}
int FIND(register int t)
{
register int S=0;
while (t)
{
S^=Tr[t];
t-=low(t);
}
return S;
}
void change(register int t,register int l,register int r,int x)
{
register int mid=(l+r)/2;
++tr[t][2];
if (l==r) return;
if (x<=mid)
{
New(t,0);
change(tr[t][0],l,mid,x);
}
else
{
New(t,1);
change(tr[t][1],mid+1,r,x);
}
}
void exchange(register int fa1,register int fa2,register int t1,register int t2,register int l,register int r,int x,int y)
{
register int mid=(l+r)/2;
if (x<=l && r<=y)
{
swap(tr[fa1][tr[fa1][1]==t1],tr[fa2][tr[fa2][1]==t2]);
return;
}
if (x<=mid && (tr[tr[t1][0]][2] || tr[tr[t2][0]][2]))
{
New(t1,0);
New(t2,0);
exchange(t1,t2,tr[t1][0],tr[t2][0],l,mid,x,y);
}
if (mid<y && (tr[tr[t1][1]][2] || tr[tr[t2][1]][2]))
{
New(t1,1);
New(t2,1);
exchange(t1,t2,tr[t1][1],tr[t2][1],mid+1,r,x,y);
}
// cout<<tr[t1][2]<<" "<<tr[tr[t1][0]][2]+tr[tr[t1][1]][2]<<endl;
tr[t1][2]=tr[tr[t1][0]][2]+tr[tr[t1][1]][2];
tr[t2][2]=tr[tr[t2][0]][2]+tr[tr[t2][1]][2];
}
void find(register int t,register int l,register int r,int x,int y)
{
register int mid=(l+r)/2;
if (x<=l && r<=y)
{
Find+=tr[t][2];
return;
}
if (x<=mid && tr[tr[t][0]][2])
find(tr[t][0],l,mid,x,y);
if (Find) return;
if (mid<y && tr[tr[t][1]][2])
find(tr[t][1],mid+1,r,x,y);
}
int main()
{
// freopen("A7_9_3.in","r",stdin);
// freopen("A7_9_3.out","w",stdout);
fread(s1,1,1400001,stdin);
n=getint();
len=1024;
fo(i,1,n)
{
a[i]=getint();
CHANGE(n-i+1,a[i]);
}
k=0;
fd(i,n,1)
{
k^=a[i];
change(k+1,1,n,i);
}
Q=getint();
for (;Q;--Q)
{
R=getint(),A=getint(),B=getint();
s=FIND(n-R+1);
// cout<<" "<<s<<endl;
// if (Q==6- 3)
// {
// fo(i,0,1023)
// {
// Find=0;
// find(i+1,1,n,2,2);
//
//// cout<<Find<<endl;
// if (Find)
// cout<<i<<" "<<a[R]<<endl;
// }
// }
fo(I,0,a[R]-1)
{
Find=0;
find((I^s)+1,1,n,A,B);
if (Find)
break;
}
// Find=0;
// find(s+1,1,n,A,B);
// cout<<s<<" "<<Find<<" "<<A<<" "<<B<<endl;
// return 0;
if (I<a[R])
{
printf("%d\n",a[R]-I);
s=a[R]^I;
l=low(s);
// cout<<s<<" "<<l<<endl;
fo(i,0,1023)
if (i&l)
{
// if (Q==6-2 && (i^s)==4)
// {
// cout<<tr[i+1][2]<<" "<<tr[(i^s)+1][2]<<endl;
// }
if (R<n)
exchange(0,0,i+1,(i^s)+1,1,n,1,R);
else
{
swap(tr[i+1][0],tr[(i^s)+1][0]);
swap(tr[i+1][1],tr[(i^s)+1][1]);
swap(tr[i+1][2],tr[(i^s)+1][2]);
}
// if (Q==6-2 && (i^s)==4)
// cout<<tr[i+1][2]<<" "<<tr[(i^s)+1][2]<<endl;
// if (Q==6-2 && (i^s)==4)
// {
// if (Q==6- 2)
// {
// fo(i,0,1023)
// {
// Find=0;
// find(i+1,1,n,2,2);
//
// // cout<<Find<<endl;
// if (Find)
// cout<<i<<" "<<a[R]<<endl;
// }
// }
// return 0;
// }
}
a[R]=I;
CHANGE(n-R+1,s);
}
else
printf("-1\n");
}
}