2017东北地区赛D题 splay

来源:互联网 发布:家常菜谱软件下载 编辑:程序博客网 时间:2024/05/22 11:56

题意: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 longint 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;}/*151 7 14 7 9 4 18 18 2 4 5 5 1 7 1152 1 140 5 100 11 141 6 82 2 72 2 130 5 82 8 120 4 132 6 102 8 122 9 122 1 120 2 90 6 9*/

阅读全文
0 0
原创粉丝点击