题意:
有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