zoukankan      html  css  js  c++  java
  • BZOJ

    题目链接

    交换两个数的位置,只有位于两个数之间的部分会受到影响,因此只需要考虑两个数之间有多少数对a[l]和a[r]产生的贡献发生了变化即可。

    感觉像是个带修改的二维偏序问题。(修改点$(x,y)$的值,维护和查询位于$(x_1,y_1)$与$(x_2,y_2)$之间的点的个数)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=2e4+10,inf=0x3f3f3f3f;
     5 int n,m,n2,rt[N<<2],ls[N*200],rs[N*200],sum[N*200],tot,a[N],b[N],ans;
     6 #define lson (u<<1)
     7 #define rson (u<<1|1)
     8 #define mid ((l+r)>>1)
     9 void upd2(int p,int x,int& u,int l=1,int r=n2) {
    10     if(!u)u=++tot;
    11     sum[u]+=x;
    12     if(l==r)return;
    13     p<=mid?upd2(p,x,ls[u],l,mid):upd2(p,x,rs[u],mid+1,r);
    14 }
    15 int qry2(int L,int R,int& u,int l=1,int r=n2) {
    16     if(l>=L&&r<=R)return sum[u];
    17     if(l>R||r<L)return 0;
    18     return qry2(L,R,ls[u],l,mid)+qry2(L,R,rs[u],mid+1,r);
    19 }
    20 void upd(int p,int x,int dx,int u=1,int l=1,int r=n) {
    21     upd2(x,dx,rt[u]);
    22     if(l==r)return;
    23     p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+1,r);
    24 }
    25 int qry(int L,int R,int L2,int R2,int u=1,int l=1,int r=n) {
    26     if(l>=L&&r<=R)return qry2(L2,R2,rt[u]);
    27     if(l>R||r<L)return 0;
    28     return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+1,r);
    29 }
    30 int main() {
    31     scanf("%d",&n);
    32     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    33     for(int i=1; i<=n; ++i)b[i]=a[i];
    34     sort(b+1,b+1+n),n2=unique(b+1,b+1+n)-(b+1);
    35     for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+n2,a[i])-b;
    36     for(int i=1; i<=n; ++i)ans+=qry(1,n,a[i]+1,n2),upd(i,a[i],1);
    37     printf("%d
    ",ans);
    38     scanf("%d",&m);
    39     while(m--) {
    40         int l,r;
    41         scanf("%d%d",&l,&r);
    42         if(l>r)swap(l,r);
    43         if(l==r||a[l]==a[r]);
    44         else {
    45             if(a[l]<a[r])ans+=qry(l+1,r-1,a[l]+1,a[r])+qry(l+1,r-1,a[l],a[r]-1)+1;
    46             else ans-=qry(l+1,r-1,a[r]+1,a[l])+qry(l+1,r-1,a[r],a[l]-1)+1;
    47             upd(l,a[l],-1),upd(l,a[r],1);
    48             upd(r,a[r],-1),upd(r,a[l],1);
    49             swap(a[l],a[r]);
    50         }
    51         printf("%d
    ",ans);
    52     }
    53     return 0;
    54 }

    还有理论上能够AC的线段树套treap的版本,可惜常数太大TLE了~QAQ~

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=2e4+10,inf=0x3f3f3f3f;
     5 int n,m,n2,rt[N<<2],ch[N*30][2],val[N*30],siz[N*30],rd[N*30],tot,a[N],b[N],ans;
     6 #define lson (u<<1)
     7 #define rson (u<<1|1)
     8 #define mid ((l+r)>>1)
     9 void pu(int u) {siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;}
    10 int newnode(int x) {int u=++tot; ch[u][0]=ch[u][1]=0,siz[u]=1,val[u]=x,rd[u]=rand(); return u;}
    11 void rot(int& u,int f) {
    12     int v=ch[u][f];
    13     ch[u][f]=ch[v][f^1],ch[v][f^1]=u;
    14     pu(u),pu(v),u=v;
    15 }
    16 void ins(int& u,int x) {
    17     if(!u) {u=newnode(x); return;}
    18     int f=x>val[u];
    19     ins(ch[u][f],x);
    20     if(rd[ch[u][f]]>rd[u])rot(u,f);
    21     if(u)pu(u);
    22 }
    23 void del(int& u,int x) {
    24     if(!u)return;
    25     if(val[u]==x) {
    26         if(!ch[u][0]||!ch[u][1])u=ch[u][0]|ch[u][1];
    27         else {
    28             int f=rd[ch[u][1]]>rd[ch[u][0]];
    29             rot(u,f),del(ch[u][f^1],x);
    30         }
    31     } else del(ch[u][x>val[u]],x);
    32     if(u)pu(u);
    33 }
    34 int lb(int u,int x) {
    35     int ret=0;
    36     for(; u; u=ch[u][x>val[u]])if(val[u]>=x)ret=val[u];
    37     return ret;
    38 }
    39 int ub(int u,int x) {
    40     int ret=0;
    41     for(; u; u=ch[u][x>=val[u]])if(val[u]>x)ret=val[u];
    42     return ret;
    43 }
    44 int rnk(int u,int x) {
    45     int ret=0;
    46     for(; u; u=ch[u][x>val[u]])if(x>val[u])ret+=siz[ch[u][0]]+1;
    47     return ret+1;
    48 }
    49 int sum(int u,int l,int r) {return l>r?0:rnk(u,ub(u,r))-rnk(u,lb(u,l));}
    50 void upd(int p,int x,int dx,int u=1,int l=1,int r=n) {
    51     dx==1?ins(rt[u],x):del(rt[u],x);
    52     if(l==r)return;
    53     p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+1,r);
    54 }
    55 int qry(int L,int R,int L2,int R2,int u=1,int l=1,int r=n) {
    56     if(l>=L&&r<=R)return sum(rt[u],L2,R2);
    57     if(l>R||r<L)return 0;
    58     return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+1,r);
    59 }
    60 void build(int u=1,int l=1,int r=n) {
    61     ins(rt[u],~inf),ins(rt[u],inf);
    62     if(l==r)return;
    63     build(lson,l,mid),build(rson,mid+1,r);
    64 }
    65 int main() {
    66     srand(time(0));
    67     scanf("%d",&n);
    68     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    69     for(int i=1; i<=n; ++i)b[i]=a[i];
    70     sort(b+1,b+1+n),n2=unique(b+1,b+1+n)-(b+1);
    71     for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+n2,a[i])-b;
    72     build();
    73     for(int i=1; i<=n; ++i)ans+=qry(1,n,a[i]+1,n2),upd(i,a[i],1);
    74     printf("%d
    ",ans);
    75     scanf("%d",&m);
    76     while(m--) {
    77         int l,r;
    78         scanf("%d%d",&l,&r);
    79         if(l>r)swap(l,r);
    80         if(l==r||a[l]==a[r]);
    81         else {
    82             if(a[l]<a[r])ans+=qry(l+1,r-1,a[l]+1,a[r])+qry(l+1,r-1,a[l],a[r]-1)+1;
    83             else ans-=qry(l+1,r-1,a[r]+1,a[l])+qry(l+1,r-1,a[r],a[l]-1)+1;
    84             upd(l,a[l],-1),upd(l,a[r],1);
    85             upd(r,a[r],-1),upd(r,a[l],1);
    86             swap(a[l],a[r]);
    87         }
    88         printf("%d
    ",ans);
    89     }
    90     return 0;
    91 }

     后续:我把treap的区间求和方式改了稍微改了一下,卡时过掉了~~

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=2e4+10,inf=0x3f3f3f3f;
     5 int n,m,n2,rt[N<<2],ch[N*30][2],val[N*30],siz[N*30],rd[N*30],tot,a[N],b[N],ans;
     6 #define lson (u<<1)
     7 #define rson (u<<1|1)
     8 #define mid ((l+r)>>1)
     9 void pu(int u) {siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;}
    10 int newnode(int x) {int u=++tot; ch[u][0]=ch[u][1]=0,siz[u]=1,val[u]=x,rd[u]=rand(); return u;}
    11 void rot(int& u,int f) {
    12     int v=ch[u][f];
    13     ch[u][f]=ch[v][f^1],ch[v][f^1]=u;
    14     pu(u),pu(v),u=v;
    15 }
    16 void ins(int& u,int x) {
    17     if(!u) {u=newnode(x); return;}
    18     int f=x>val[u];
    19     ins(ch[u][f],x);
    20     if(rd[ch[u][f]]>rd[u])rot(u,f);
    21     if(u)pu(u);
    22 }
    23 void del(int& u,int x) {
    24     if(!u)return;
    25     if(val[u]==x) {
    26         if(!ch[u][0]||!ch[u][1])u=ch[u][0]|ch[u][1];
    27         else {
    28             int f=rd[ch[u][1]]>rd[ch[u][0]];
    29             rot(u,f),del(ch[u][f^1],x);
    30         }
    31     } else del(ch[u][x>val[u]],x);
    32     if(u)pu(u);
    33 }
    34 int lb(int u,int x) {
    35     int ret=0;
    36     for(; u; u=ch[u][x>val[u]])if(x>val[u])ret+=siz[ch[u][0]]+1;
    37     return ret;
    38 }
    39 int ub(int u,int x) {
    40     int ret=0;
    41     for(; u; u=ch[u][x>=val[u]])if(x>=val[u])ret+=siz[ch[u][0]]+1;
    42     return ret;
    43 }
    44 int sum(int u,int l,int r) {return ub(u,r)-lb(u,l);}
    45 void upd(int p,int x,int dx,int u=1,int l=1,int r=n) {
    46     dx==1?ins(rt[u],x):del(rt[u],x);
    47     if(l==r)return;
    48     p<=mid?upd(p,x,dx,lson,l,mid):upd(p,x,dx,rson,mid+1,r);
    49 }
    50 int qry(int L,int R,int L2,int R2,int u=1,int l=1,int r=n) {
    51     if(l>=L&&r<=R)return sum(rt[u],L2,R2);
    52     if(l>R||r<L)return 0;
    53     return qry(L,R,L2,R2,lson,l,mid)+qry(L,R,L2,R2,rson,mid+1,r);
    54 }
    55 int main() {
    56     srand(time(0));
    57     scanf("%d",&n);
    58     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    59     for(int i=1; i<=n; ++i)b[i]=a[i];
    60     sort(b+1,b+1+n),n2=unique(b+1,b+1+n)-(b+1);
    61     for(int i=1; i<=n; ++i)a[i]=lower_bound(b+1,b+1+n2,a[i])-b;
    62     for(int i=1; i<=n; ++i)ans+=qry(1,n,a[i]+1,n2),upd(i,a[i],1);
    63     printf("%d
    ",ans);
    64     scanf("%d",&m);
    65     while(m--) {
    66         int l,r;
    67         scanf("%d%d",&l,&r);
    68         if(l>r)swap(l,r);
    69         if(l==r||a[l]==a[r]);
    70         else {
    71             if(a[l]<a[r])ans+=qry(l+1,r-1,a[l]+1,a[r])+qry(l+1,r-1,a[l],a[r]-1)+1;
    72             else ans-=qry(l+1,r-1,a[r]+1,a[l])+qry(l+1,r-1,a[r],a[l]-1)+1;
    73             upd(l,a[l],-1),upd(l,a[r],1);
    74             upd(r,a[r],-1),upd(r,a[l],1);
    75             swap(a[l],a[r]);
    76         }
    77         printf("%d
    ",ans);
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    P2048 [NOI2010]超级钢琴 (rmq +堆+贪心)
    题解 P4799 【[CEOI2015 Day2]世界冰球锦标赛】
    洛谷 P1360 [USACO07MAR]Gold Balanced Lineup G (前缀和+思维)
    洛谷 P4880 抓住czx
    洛谷 P2471 [SCOI2007]降雨量
    洛谷 P4688 [Ynoi2016]掉进兔子洞 (看到题目背景,galgame玩家狂喜)
    洛谷 P2101 命运石之门的选择 (分治)
    留言版
    【游记】OI 2020(在更)
    类欧几里得算法
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10696632.html
Copyright © 2011-2022 走看看