【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         
原文地址:https://www.cnblogs.com/myx12345/p/9702352.html