【BZOJ3333】排队计划 树状数组+线段树
【BZOJ3333】排队计划
Description
Input
Output
Sample Input
6 2
160 163 164 161 167 160
2
3
160 163 164 161 167 160
2
3
Sample Output
6
3
1
3
1
HINT
题解:本题的思路比较好,可惜我只想到了一半。
先用树状数组求出f[i],代表i和后面的人能构成多少逆序对。然后我们发现,每次放哨时,只有出列的那些同学的f值会发生变化(变成0),而其他人的f值不发生改变,所以我们将这些出列的同学找出来暴力清零即可。
但是放哨后高度的排列顺序会变啊,这样会不会对其他询问有影响呢?显然不会啊!f值都清零了还会有什么影响?所以我们可以用线段树维护区间最大值,这样就能找到每个人后面所有比它小的了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; typedef long long ll; const int maxn=500010; struct node { int val,org; }p[maxn]; int n,m,nm; ll ans; int f[maxn],s[maxn],v[maxn],ps[maxn<<2]; bool cmp(const node &a,const node &b) { return a.val<b.val; } inline void updata(int x) { for(int i=x;i<=nm;i+=i&-i) s[i]++; } inline int query(int x) { int i,ret=0; for(i=x;i;i-=i&-i) ret+=s[i]; return ret; } inline int MX(int a,int b) { return v[a]<v[b]?a:b; } void build(int l,int r,int x) { if(l==r) { ps[x]=l; return ; } int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); ps[x]=MX(ps[lson],ps[rson]); } int query(int l,int r,int x,int a,int b) { if(a<=l&&r<=b) return ps[x]; int mid=(l+r)>>1; if(b<=mid) return query(l,mid,lson,a,b); if(a>mid) return query(mid+1,r,rson,a,b); return MX(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b)); } void updata(int l,int r,int x,int a) { if(l==r) return ; int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a); else updata(mid+1,r,rson,a); ps[x]=MX(ps[lson],ps[rson]); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,a,b,c; for(i=1;i<=n;i++) p[i].val=rd(),p[i].org=i; sort(p+1,p+n+1,cmp); for(i=1;i<=n;i++) { if(p[i].val>p[i-1].val) nm++; v[p[i].org]=nm; } for(i=n;i;i--) f[i]=query(v[i]-1),ans+=f[i],updata(v[i]); build(1,n,1); printf("%lld\n",ans); for(i=1;i<=m;i++) { a=rd(),c=v[a]; if(c!=1<<30) { while(1) { b=query(1,n,1,a,n); if(v[b]>c) break; ans-=f[b],v[b]=1<<30,updata(1,n,1,b); } } printf("%lld\n",ans); } return 0; }//6 2 160 163 164 161 167 160 2 3
| 欢迎来原网站坐坐! >原文链接<