bzoj 3192: [JLOI2013]删除物品
2017-09-18 10:31
309 查看
题意:有两堆物品,每个物品有个权值。每次可以将其中一个堆的顶端的物品移到另一堆的顶端,假如它的权值是所有物品里最大的,就可以把它删掉。问最少几次移动可以删除所以物品。
题解:直接模拟+线段树。
跑的贼慢。。。
题解:直接模拟+线段树。
跑的贼慢。。。
#include<bits/stdc++.h> using namespace std; int n1,n2,n,num=0,a[100010]; struct tree { int l,r,lc,rc,s,m; }tr[200010]; long long ans=0; map<int,int>pos; int bt(int l,int r) { int i=++num; tr[i]={l,r,0,0,1,a[l]}; if(l<r) { int md=l+r>>1; tr[i].lc=bt(l,md); tr[i].rc=bt(md+1,r); tr[i].s=tr[tr[i].lc].s+tr[tr[i].rc].s; tr[i].m=max(tr[tr[i].lc].m,tr[tr[i].rc].m); } return i; } void chg(int i,int x,int y) { if(tr[i].l==tr[i].r) { tr[i].s=tr[i].m=y; return; } int md=tr[i].l+tr[i].r>>1,lc=tr[i].lc,rc=tr[i].rc; if(x<=md) chg(lc,x,y); else chg(rc,x,y); tr[i].s=tr[lc].s+tr[rc].s; tr[i].m=max(tr[lc].m,tr[rc].m); } int get(int i,int l,int r) { if(l>r) return 0; if(tr[i].l==l&&tr[i].r==r) return tr[i].s; int md=tr[i].l+tr[i].r>>1,lc=tr[i].lc,rc=tr[i].rc; if(r<=md) return get(lc,l,r); else if(l>md) return get(rc,l,r); else return get(lc,l,md)+get(rc,md+1,r); } int main() { scanf("%d%d",&n1,&n2); n=n1+n2; for(int i=n1;i>0;i--) { scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=n1+1;i<=n;i++) { scanf("%d",&a[i]); pos[a[i]]=i; } bt(1,n); int p=n1; for(int i=1;i<=n;i++) { int hh=pos[tr[1].m]; if(hh<=p) { ans+=get(1,hh+1,p); } else { ans+=get(1,p+1,hh-1); } chg(1,hh,0); // printf("%d %d %lld\n",p,hh,ans); p=hh; } printf("%lld",ans); }
相关文章推荐
- BZOJ3192 [JLOI2013]删除物品(树状数组)
- BZOJ3192: [JLOI2013]删除物品(洛谷P3253)
- bzoj3192 [JLOI2013]删除物品
- 【BZOJ3192】【JLOI2013】删除物品 模拟
- BZOJ 3192: [JLOI2013]删除物品
- 【bzoj 3192】: [JLOI2013]删除物品 树状数组+想法题
- [bzoj3192] [JLOI2013]删除物品
- [bzoj3192][JLOI2013]删除物品_树状数组_栈
- BZOJ 3192([JLOI2013]删除物品-双堆转头并头队列)
- [bzoj3192][JLOI2013]删除物品 树状数组
- 【BZOJ3192】【JLOI2013】删除物品
- [BZOJ]3192: [JLOI2013]删除物品 树状数组
- BZOJ3192 [JLOI2013]删除物品
- 【BZOJ 3192】 [JLOI2013]删除物品
- bzoj3192 [JLOI2013]删除物品 树状数组
- bzoj 3192: [JLOI2013]删除物品
- bzoj 3192: [JLOI2013]删除物品
- BZOJ3192: [JLOI2013]删除物品 树状数组
- bzoj3192 [JLOI2013]删除物品
- [bzoj 3192] [JLOI2013]删除物品