bzoj3295: [Cqoi2011]动态逆序对
2017-03-29 08:51
274 查看
链接
http://www.lydsy.com/JudgeOnline/problem.php?id=3295题解
叫这道题目卡了一下午+一晚上+一早晨。显然删掉一个数之后,逆序对减少的量是前面比它大的数和后面比它小的数。
那就主席树啊,但是修改怎么办?要修改一连串主席树,这样就慢了,所以就想到树状数组套主席树。
每棵主席树ta[x]是(x-lowbit(x),x]这段区间的权值主席树。然后修改、查询都变成log2的了。
但是卡内存…Nlog2N是承受不起的。所以主席树插入的时候,没必要就不要新建节点。还有struct里不要存l和r,调用函数的时候一块传进去就好。
我开了107的节点…
听说正解是CDQ分治…(捂脸)
代码
//主席树 #include <cstdio> #include <algorithm> #define maxnd 10000000 #define maxn 100010 #define ll long long #define lowbit(x) (x&-x) using namespace std; int N, M, q[maxn], a[maxn], ans[maxn], tmp[maxn], ndtot, table[maxn], cons=0x7fffffff; ll now; struct segtree { int sum; segtree *ch[2]; }pool[maxnd], *emp, *ta[maxn]; int read(int x=0) { char c=getchar(); while(c<48 or c>57)c=getchar(); while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48,c=getchar(); return x; } void ins(segtree *pre, segtree *now, int L, int R, int pos, int d) { int mid=(L+R)>>1; segtree *p; *now=*pre; now->sum+=d; if(L==R)return; if(pos<=mid) { if(pre->ch[0]<=pool+cons)p=pool+ ++ndtot;else p=pre->ch[0];*p=*pre->ch[0]; ins(pre->ch[0],now->ch[0]=p,L,mid,pos,d); } if(pos>mid) { if(pre->ch[1]<=pool+cons)p=pool+ ++ndtot;else p=pre->ch[1];*p=*pre->ch[1]; ins(pre->ch[1],now->ch[1]=p,mid+1,R,pos,d); } } ll segsum(segtree *p, int L, int R, int l, int r) { int mid=(L+R)>>1; ll ans=0; if(l<=L and r>=R)return p->sum; if(l<=mid)ans+=segsum(p->ch[0],L,mid,l,r); if(r>mid)ans+=segsum(p->ch[1],mid+1,R,l,r); return ans; } void add(int pos, int x, int v) { for(;pos<=N;pos+=lowbit(pos)) { segtree *p=pool+ ++ndtot; ins(ta[pos],p,1,N,x,v); ta[pos]=p; } } ll sum(int pos, int l, int r) { ll ans=0; for(;pos;pos-=lowbit(pos))ans+=segsum(ta[pos],1,N,l,r); return ans; } void build(segtree *p, int L, int R) { int mid=(L+R)>>1; if(L==R)return; build(p->ch[0]=pool+ ++ndtot,L,mid); build(p->ch[1]=pool+ ++ndtot,mid+1,R); } void init() { int i; N=read(), M=read(); for(i=1;i<=N;i++)a[i]=read(),table[a[i]]=i; build(emp=pool+ ++ndtot,1,N); cons=ndtot; for(i=1;i<=N;i++)ta[i]=pool+ ++ndtot, *ta[i]=*emp; for(i=1;i<=N;i++) { now+=sum(i,a[i],N); add(i,a[i],1); } } void work() { int i, num, pos; for(i=1;i<=M;i++) { printf("%lld\n",now); pos=table[num=read()]; if(pos!=1)now-=sum(pos-1,num,N); if(pos!=N)now-=sum(N,1,num)-sum(pos,1,num); add(pos,num,-1); } } int main() { init(); work(); return 0; }
相关文章推荐
- BZOJ3295: [Cqoi2011]动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对 三维数点
- bzoj3295[Cqoi2011]动态逆序对 cdq分治(树套树/主席树)
- bzoj3295: [Cqoi2011]动态逆序对
- bzoj3295【CQOI2011】动态逆序对
- BZOJ3295: [Cqoi2011]动态逆序对
- bzoj3295[Cqoi2011]动态逆序对 树套树
- BZOJ3295: [Cqoi2011]动态逆序对
- BZOJ3295 [Cqoi2011]动态逆序对 【CDQ分治】
- bzoj3295: [Cqoi2011]动态逆序对
- BZOJ3295 [Cqoi2011]动态逆序对 【CDQ分治】
- BZOJ3295 CQOI2011 动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- BZOJ3295: [Cqoi2011]动态逆序对
- [CQOI2011]动态逆序对
- [bzoj]3295: [Cqoi2011]动态逆序对 主席树
- 【BZOJ3295】【CQOI2011】动态逆序对
- bzoj3295[Cqoi2011] 动态逆序对
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- bzoj3295 [Cqoi2011]动态逆序对