题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3295
题目--洛谷3157:https://www.luogu.org/problemnew/show/P3157
题目--洛谷3193:https://www.luogu.org/problemnew/show/P1393
用树套树做的。还能用主席树和CDQ分治做。现在还没用它们做。
有点卡空间。线段树节点的*100怎么算?
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=1e5+5; int n,m,f[N],rt[N],tot,ps[N]; ll ans; struct Node{ int ls,rs,sum; }a[N*100]; int getsm(int x) { int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret; } void addsm(int x) { for(;x<=n;x+=(x&-x))f[x]++; } void insert(int &cr,int l,int r,int p,int fx) { if(!cr)cr=++tot;a[cr].sum+=fx; if(l==r)return; int mid=((l+r)>>1); if(p<=mid)insert(a[cr].ls,l,mid,p,fx); else insert(a[cr].rs,mid+1,r,p,fx); } void insert(int x,int v,int fx) { for(;x<=n;x+=(x&-x))insert(rt[x],1,n,v,fx); } int query(int cr,int l,int r,int x) { if(r<=x)return a[cr].sum; int mid=((l+r)>>1); if(x<=mid)return query(a[cr].ls,l,mid,x); return a[a[cr].ls].sum+query(a[cr].rs,mid+1,r,x); } int query(int x,int v) { int ret=0;for(;x;x-=(x&-x))ret+=query(rt[x],1,n,v);return ret; } int pre(int p,int x) { return query(p,n)-query(p,x); } int suf(int p,int x) { return query(n,x)-query(p,x); } int main() { scanf("%d%d",&n,&m);int x; for(int i=1;i<=n;i++) { scanf("%d",&x);ans+=getsm(n)-getsm(x); addsm(x);insert(i,x,1);ps[x]=i; } for(int i=1;i<=m;i++) { printf("%lld\n",ans);scanf("%d",&x); ans-=pre(ps[x],x)+suf(ps[x],x); insert(ps[x],x,-1); } return 0; }
加上离散化就能过洛谷3193了。通过数喜+1。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=4e4+5; int n,m,f[N],rt[N],tot,vl[N]; ll ans,tp[N],t[N]; struct Node{ int ls,rs,sum; }a[N*100]; int getsm(int x) { int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret; } void addsm(int x) { for(;x<=n;x+=(x&-x))f[x]++; } void insert(int &cr,int l,int r,int p,int fx) { if(!cr)cr=++tot;a[cr].sum+=fx; if(l==r)return; int mid=((l+r)>>1); if(p<=mid)insert(a[cr].ls,l,mid,p,fx); else insert(a[cr].rs,mid+1,r,p,fx); } void insert(int x,int v,int fx) { for(;x<=n;x+=(x&-x))insert(rt[x],1,n,v,fx); } int query(int cr,int l,int r,int x) { if(r<=x)return a[cr].sum; int mid=((l+r)>>1); if(x<=mid)return query(a[cr].ls,l,mid,x); return a[a[cr].ls].sum+query(a[cr].rs,mid+1,r,x); } int query(int x,int v) { int ret=0;for(;x;x-=(x&-x))ret+=query(rt[x],1,n,v);return ret; } int pre(int p,int x) { return query(p,n)-query(p,x); } int suf(int p,int x) { return query(n,x)-query(p,x); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lld",&t[i]),tp[i]=t[i]; sort(tp+1,tp+n+1);int cnt=unique(tp+1,tp+n+1)-tp-1; for(int i=1;i<=n;i++)vl[i]=lower_bound(tp+1,tp+cnt+1,t[i])-tp; for(int i=1;i<=n;i++) { ans+=getsm(n)-getsm(vl[i]); addsm(vl[i]);insert(i,vl[i],1); } printf("%lld ",ans);int x; for(int i=1;i<=m;i++) { scanf("%d",&x); ans-=pre(x,vl[x])+suf(x,vl[x]); insert(x,vl[x],-1);printf("%lld ",ans); } return 0; }