[填坑]一直遗忘的树套树版本动态CDQ
题解: 树状数组维护动态开点线段树 实质上是树状数组对应区间维护一颗动态开点线段树 方便对应区间小于x的个数
#include <bits/stdc++.h> #define ll long long const int MAXN=1e5+10; using namespace std; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } typedef struct node{ int l,r,sum; }node; vector<int>vec; node d[MAXN*85]; int a[MAXN],n,m,cnt,id[MAXN],rt[MAXN]; int get_id(int x){return x&(-x);} void csh(int x){ for(int i=x;i<=n;i+=get_id(i))vec.push_back(i); } void csh1(int x){ for(int i=x;i>0;i-=get_id(i))vec.push_back(i); } void update(int &x,int l,int r,int t,int vul){ if(!x)x=++cnt; d[x].sum+=vul; if(l==r)return ; int mid=(l+r)>>1; if(t<=mid)update(d[x].l,l,mid,t,vul); else update(d[x].r,mid+1,r,t,vul); } ll ans=0; void querty(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ ans+=d[x].sum;return ; } int mid=(l+r)>>1; if(ql<=mid)querty(d[x].l,l,mid,ql,qr); if(qr>mid)querty(d[x].r,mid+1,r,ql,qr); } int p[MAXN]; void add(int x){ for(;x<=n;x+=get_id(x))p[x]++; } int Sum(int x){ int ans1=0; for(;x>0;x-=get_id(x))ans1+=p[x]; return ans1; } int main(){ n=read();m=read();cnt=0; for(int i=1;i<=n;i++)a[i]=read(),id[a[i]]=i;ll sum=0; for(int i=1;i<=n;i++){ csh(i); for(int j=0;j<vec.size();j++)update(rt[vec[j]],1,n,a[i],1); vec.clear(); if(a[i]==n)continue; csh1(i); for(int j=0;j<vec.size();j++)ans=0,querty(rt[vec[j]],1,n,a[i]+1,n),sum+=ans; vec.clear(); } int t;ll num,num1,num2; printf("%lld\n",sum); for(int i=1;i<min(n,m);i++){ t=read(); csh1(id[t]);num=0,num1=0; if(t!=n){for(int j=0;j<vec.size();j++)ans=0,querty(rt[vec[j]],1,n,t+1,n),num+=ans;} if(t!=1){for(int j=0;j<vec.size();j++)ans=0,querty(rt[vec[j]],1,n,1,t-1),num1+=ans;} vec.clear(); sum-=num+t-1-num1-Sum(t); csh(id[t]); for(int j=0;j<vec.size();j++)update(rt[vec[j]],1,n,t,-1); vec.clear(); add(t);printf("%lld\n",sum); } return 0; }
3295: [Cqoi2011]动态逆序对
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7107 Solved: 2526
[Submit][Status][Discuss]
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删
除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
以下n行每行包含一个1到n之间的正整数,即初始排列。
以下m行每行一个正整数,依次为每次删除的元素。
N<=100000 M<=50000
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。