题意:25W个序列 支持三个操作:
1 给你一个长度为偶数的区间 交换区间相邻的元素 区间里 第1个和第2个换 第3个和第4个换 第5个和第6个换
2 给你一个长度为奇数的区间 将区间翻转
3 求区间的和
题解:将区间元素按下标奇偶分成2个splay 对于第1个操作直接交换区间 第2个操作由于是奇数长度的区间 所以把范围两个splay内的区间直接翻转就好了
PS:场上没有想到按奇偶分组 然后一直在操作一讨论奇偶性,然后发现这似乎是个不可能的操作?GG 最后两个半小时几乎什么都没有干,就这样划水还拿了一等,如果是ICPC估计就真的GG了....... (我用自己的数据测的是对的,直到我发blog时网上还没有挂出比赛题)
#include <bits/stdc++.h>
using namespace std;
#define pf printf
#define ss system("pause");
#define ps puts("");
#define orz printf("orz\n");
#define maxn 550000
#define INF 0x3f3f3f3f
#define sint long long
int pfg;
inline int getint()
{
int res=0,f=1;char c;
while(c=getchar(),c<'0'||c>'9'){if(c=='-')f=-1;}
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')res=res*10+c-'0';
return res*f;
}
int tr[maxn][2],fa[maxn],root,n,m,rt0,rt1;
int v[maxn],val[maxn],a[maxn],siz[maxn],cnt;
sint sum[maxn];
bool rev[maxn];
void pushup(int rt)
{
int l=tr[rt][0],r=tr[rt][1];
siz[rt]=siz[l]+siz[r]+1;
sum[rt]=sum[l]+sum[r]+val[rt];
}
void pushdown(int rt)
{
if(rev[rt])
{
int l=tr[rt][0],r=tr[rt][1];
rev[rt]^=1;rev[r]^=1;rev[l]^=1;
swap(tr[l][0],tr[l][1]);swap(tr[r][0],tr[r][1]);
}
}
void rotate(int x,int &rt)
{
int l,r,z,y;
y=fa[x];z=fa[y];
if(x==tr[y][0]) l=0;
else l=1;r=1^l;
if(rt==y) rt=x;
else
{
if(tr[z][0]==y) tr[z][0]=x;
else tr[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x,int &rt)
{
int y,z;
while(x!=rt)
{
y=fa[x];z=fa[y];
if(y!=rt)
{
if((tr[y][0]==x)^(tr[z][0]==y)) rotate(x,rt);
else rotate(y,rt);
}
rotate(x,rt);
}
}
int select(int now,int rk)
{
if(rev[now]) pushdown(now);
int l=tr[now][0],r=tr[now][1];
int rak=siz[l]+1;
if(rak==rk) return now;
if(rak>rk) return select(l,rk);
else return select(r,rk-rak);
}
void solve_rever(int x)
{
rev[x]^=1;
swap(tr[x][0],tr[x][1]);
}
void build(int l,int r,int f)
{
if(l>r)return;
int now=l,last=f;
if(l==r)
{
sum[now]=val[now]=v[l]; fa[now]=last;siz[now]=1;
if(l<f)tr[last][0]=now;
else tr[last][1]=now;
return;
}
int mid=(l+r)>>1;now=mid;
build(l,mid-1,mid);
build(mid+1,r,mid);
val[now]=v[mid];fa[now]=last;
pushup(now);
if(mid<f)tr[last][0]=now;
else tr[last][1]=now;
}
void get_trees()
{
int l,r;
cnt++;v[cnt]=0; l=cnt;
for(int i=1;i<=n;i+=2)
{
cnt++;v[cnt]=a[i];
}
cnt++;v[cnt]=0; r=cnt;
rt1=(l+r)>>1;
build(l,r,0);
cnt++;v[cnt]=0; l=cnt;
for(int i=2;i<=n;i+=2)
{
cnt++;v[cnt]=a[i];
}
cnt++;v[cnt]=0; r=cnt;
rt0=(l+r)>>1;
build(l,r,0);
}
void solve_0(int l,int r)
{
int odd_rt =l/2+1;
int even_rt=(l-1)/2+1;
int len =(r-l+1)/2;
int x1,y1;
x1=select(rt1,odd_rt);
y1=select(rt1,odd_rt+len+1);
splay(x1,rt1);
splay(y1,tr[x1][1]);
int x0,y0;
x0=select(rt0,even_rt);
y0=select(rt0,even_rt+len+1);
splay(x0,rt0);
splay(y0,tr[x0][1]);
swap(fa[tr[y1][0]],fa[tr[y0][0]]);
swap(tr[y1][0],tr[y0][0]);
pushup(y1);pushup(x1);
pushup(y0);pushup(x0);
}
void dfs(int rt)
{
pushdown(rt);
if(val[rt]) pf("%d %d %d\n",val[rt],sum[rt],fa[rt]);
if(tr[rt][0]) dfs(tr[rt][0]);
if(tr[rt][1]) dfs(tr[rt][1]);
}
void solve_1(int l, int r)
{
int odd_rt = l/2 + 1;
int even_rt =(l-1)/2 + 1;
int odd_len =(r-l)/2;
int even_len = odd_len + 1;
if (l&1) swap(odd_len,even_len);
int x,y;
x=select(rt1,odd_rt);
y=select(rt1,odd_rt+odd_len+1);
splay(x,rt1);
splay(y,tr[x][1]);
solve_rever(tr[y][0]);
x=select(rt0,even_rt);
y=select(rt0,even_rt+even_len+1);
splay(x,rt0);
splay(y,tr[x][1]);
solve_rever(tr[y][0]);
}
sint qsum(int l, int r)
{
int odd_rt=l/2 + 1;
int even_rt=(l-1)/2 + 1;
int odd_len=(r+1)/2-l/2;
int even_len=r/2-(l-1)/2;
sint ans=0;
int x,y;
x=select(rt1,odd_rt);
y=select(rt1,odd_rt+odd_len+1);
splay(x,rt1);
splay(y,tr[x][1]);
ans +=sum[tr[y][0]];
x=select(rt0,even_rt);
y=select(rt0,even_rt+even_len+1);
splay(x,rt0);
splay(y,tr[x][1]);
ans +=sum[tr[y][0]];
return ans;
}
int main()
{
n=getint();
for(int i=1;i<=n;i++) a[i]=getint();
get_trees();
int op,x,y,z;
m=getint();
for(int i=1;i<=m;i++)
{
op=getint();x=getint();y=getint();
if(op==0) solve_0(x,y);
if(op==1) solve_1(x,y);
if(op==2) pf("%lld\n",qsum(x,y));
}
return 0;
}
/*
15
1 7 14 7 9 4 18 18 2 4 5 5 1 7 1
15
2 1 14
0 5 10
0 11 14
1 6 8
2 2 7
2 2 13
0 5 8
2 8 12
0 4 13
2 6 10
2 8 12
2 9 12
2 1 12
0 2 9
0 6 9
*/