• 【ZOJ4053】Couleur(主席树,set,启发式)


    题意:

    有n个位置,每个位置上的数字是a[i],现在有强制在线的若干个单点删除操作,每次删除的位置都不同,要求每次删除之后求出最大的连续区间逆序对个数

    n<=1e5,1<=a[i]<=n

    思路:

    对于每次删除操作我们可以考虑被删除的数字的贡献

    比如区间[l,r]内删除了x这个位置,被分成了[l,x-1]与[x+1,r]两个区间

    未删除之前区间总逆序对数可以分为4个部分:[l,x-1]内部,[x+1,r]内部,跨区间,一端为x

    一个优秀的结论是内部区间和跨区间部分可以选择两端区间内较小的一段进行暴力枚举计算(启发式),这样每个位置均摊被用到了logn次

    然后用总的逆序对数减去其他3部分就是较大区间内部的逆序对数

    逆序对部分等价于求某个区间内在[l,r]之间数字的个数,显然使用主席树进行预处理

    现在还要维护区间的插入,删除与最大值,这个如果只使用一个splay似乎很难维护多个关键字

    大佬new表示并不需要splay,只需要使用set维护被删除的点,就能很快找出被删除的位置处于哪个区间

    然而我并不会set,只能照他打一遍了,真是屈辱

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<map>
      8 #include<set>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef unsigned int uint;
     14 typedef unsigned long long ull;
     15 typedef pair<int,int> PII;
     16 typedef vector<int> VI;
     17 #define fi first
     18 #define se second s
     19 #define MP make_pair
     20 #define N   110000
     21 #define MOD 1000000007
     22 #define eps 1e-8 
     23 #define pi acos(-1)
     24 #define oo 1e9
     25 
     26 struct node
     27 {
     28     int l,r,s;
     29 }t[N*45];
     30 
     31 struct data
     32 {
     33     ll x;
     34     int l,r;
     35 };
     36 
     37 ll Ans[N],f[N],ans;
     38 int a[N],root[N],cnt,n;
     39 
     40 set<int>st;
     41 typedef set<int>::iterator iter;
     42 struct setcmp
     43 {
     44     bool operator()(const data &x,const data &y)
     45     {
     46         return x.x>y.x||(x.x==y.x&&x.l<y.l)||(x.x==y.x&&x.l==y.l&&x.r<y.r);
     47     }
     48 };
     49 set<data,setcmp>S;
     50 
     51 ll query(int l,int r,int x,int y,int L,int R)
     52 {
     53     if(l>r||x>y) return 0;
     54     if(x<=l&&r<=y) return t[R].s-t[L].s;
     55     int mid=(l+r)>>1;
     56     ll ans=0;
     57     if(x<=mid) ans+=query(l,mid,x,y,t[L].l,t[R].l);
     58     if(y>mid) ans+=query(mid+1,r,x,y,t[L].r,t[R].r);
     59     return ans;
     60 }
     61 
     62 void update(int l,int r,int x,int &p)
     63 {
     64     t[++cnt]=t[p];
     65     p=cnt;
     66     t[p].s++;
     67     if(l==r) return;
     68     int mid=(l+r)>>1;
     69     if(x<=mid) update(l,mid,x,t[p].l);
     70      else update(mid+1,r,x,t[p].r);
     71 }
     72 
     73 int read()
     74 { 
     75    int v=0,f=1;
     76    char c=getchar();
     77    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     78    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     79    return v*f;
     80 }
     81 
     82 int main()
     83 {
     84     freopen("zoj4053.in","r",stdin);
     85     freopen("zoj4053.out","w",stdout);
     86     int cas;
     87     scanf("%d",&cas);
     88     while(cas--)
     89     {
     90          scanf("%d",&n);
     91         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     92         cnt=0;
     93         ans=0;
     94         st.clear();
     95         st.insert(0);
     96         st.insert(n+1);
     97         S.clear();
     98         for(int i=1;i<=n;i++)
     99         {
    100             root[i]=root[i-1];
    101             update(1,n,a[i],root[i]);
    102         }
    103         ll ans=0;
    104         for(int i=1;i<=n;i++) ans+=query(1,n,a[i]+1,n,root[0],root[i-1]);
    105         S.insert((data){ans,1,n});
    106         f[1]=ans;
    107         for(int i=1;i<=n;i++)
    108         {
    109             ans=(*S.begin()).x;
    110             Ans[i]=ans;
    111             ll x;
    112             scanf("%lld",&x);
    113             x^=ans;
    114             iter p=st.lower_bound(x);
    115             int r=*p;
    116             p--;
    117             int l=*p;
    118             l++; r--;
    119             S.erase(S.lower_bound((data){f[l],l,r}));
    120             ans=f[l];
    121             ll t1=0;
    122             ll t2=0;
    123             if(x-l<r-x)
    124             {
    125                 for(int i=l;i<x;i++)
    126                 {
    127                     t1+=query(1,n,1,a[i]-1,root[i],root[x-1]);
    128                     ans-=query(1,n,1,a[i]-1,root[i],root[r]);
    129                 }
    130                 ans-=query(1,n,1,a[x]-1,root[x],root[r]);
    131                 t2=ans;
    132             }
    133              else
    134              {
    135                  for(int i=x+1;i<=r;i++)
    136                  {
    137                      t2+=query(1,n,a[i]+1,n,root[x],root[i-1]);
    138                      ans-=query(1,n,a[i]+1,n,root[l-1],root[i-1]);
    139                  }
    140                  ans-=query(1,n,a[x]+1,n,root[l-1],root[x-1]);
    141                  t1=ans;
    142              }
    143              if(1<=x-1)
    144              {
    145                      S.insert((data){t1,l,x-1});
    146                     f[l]=t1;
    147              }
    148              if(x+1<=r)
    149              {
    150                  S.insert((data){t2,x+1,r});
    151                  f[x+1]=t2;
    152              }
    153              st.insert(x);
    154         }
    155         for(int i=1;i<n;i++) printf("%lld ",Ans[i]);
    156         printf("%lld
    ",Ans[n]); 
    157         
    158     }
    159     return 0;
    160 }
    161 
    162 
    163             
    164         
  • 相关阅读:
    DataSet调用Dispose必须吗
    Python基础
    windows下pip升级到8.1.1 及安装Selenium
    python文件编码说明 coding
    Response.End() VS Context.ApplicationInstance.CompleteRequest()
    Python练习正则
    Python2.7爬虫练习爬百度百科python词条
    未知错误:1000正在终止线程
    debug pin用
    读取文件
  • 原文地址:https://www.cnblogs.com/myx12345/p/9702352.html
Copyright © 2020-2023  润新知