BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分相关的知识,希望对你有一定的参考价值。
【题目分析】
整体二分显而易见。
自己YY了一下用树状数组区间修改,区间查询的操作。
又因为一个字母调了一下午。
貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log
懒得写了。
【代码】
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 50005 #define inf 0x3f3f3f3f #define ll long long ll n,m,cnt=0,tot=0; struct Bit_Tree{ ll a[maxn],b[maxn]; void add(ll x,ll y,ll z) { // cout<<"Add "<<x<<" "<<y<<" "<<z<<endl; for (ll i=x;i<=n;i+=i&(-i)) b[i]+=z; for (ll i=y+1;i<=n;i+=i&(-i)) b[i]-=z; for (ll i=x;i<=n;i+=i&(-i)) a[i]+=(n-x)*z; for (ll i=y+1;i<=n;i+=i&(-i)) a[i]-=(n-y-1)*z; } void init() { memset(a,0,sizeof a); memset(b,0,sizeof b); } ll getsum(ll x) { ll ret=0,tmp=0; for (ll i=x;i;i-=i&(-i)) ret+=a[i],tmp+=b[i]; return ret-(n-x-1)*tmp; } ll get(ll x,ll y) { return getsum(y)-getsum(x-1); } }t; struct data{ ll opt,id; ll x,y,z; }q[maxn<<1],q1[maxn<<1],q2[maxn<<1]; ll ans[maxn<<1],tag[maxn<<1]; void solve(ll ql,ll qr,ll l,ll r) { // cout<<"solve"<<ql<<" "<<qr<<" "<<l<<" "<<r<<endl; // cout<<"In Que"<<endl; if (ql>qr) return; if (l==r) { for (ll i=ql;i<=qr;++i) ans[q[i].id]=l; return ; } ll mid=l+r>>1,p1=0,p2=0,cnt=0; // cout<<"Mid is "<<mid<<endl; for (ll i=ql;i<=qr;++i) { // cout<<q[i].opt<<" "<<q[i].x<<" "<<q[i].y<<" "<<q[i].z<<" "<<endl; if (q[i].opt==1) { if (q[i].z<=mid) { t.add(q[i].x,q[i].y,1); cnt+=q[i].y-q[i].x+1; q1[++p1]=q[i]; } else q2[++p2]=q[i]; } else { ll tmp=t.get(q[i].x,q[i].y); // cout<<"Tmp is "<<tmp<<endl; if (q[i].z<=tmp) q1[++p1]=q[i]; else q[i].z-=tmp,q2[++p2]=q[i]; } } for (ll i=1;i<=p1;++i) { if (q1[i].opt==1) t.add(q1[i].x,q1[i].y,-1); q[ql+i-1]=q1[i]; } for (ll i=1;i<=p2;++i) q[ql+p1+i-1]=q2[i]; solve(ql,ql+p1-1,l,mid); solve(ql+p1,qr,mid+1,r); } int main() { // freopen("in.txt","r",stdin); // freopen("wa.txt","w",stdout); scanf("%lld",&n); n=maxn-1; scanf("%lld",&m); cnt=m; for (ll i=1;i<=m;++i) { scanf("%lld%lld%lld%lld",&q[i].opt,&q[i].x,&q[i].y,&q[i].z); q[i].id=i; if (q[i].opt==1) t.add(q[i].x,q[i].y,1); if (q[i].opt==2) { tag[i]=1; tot=t.get(q[i].x,q[i].y); q[i].z=tot-q[i].z+1; } } for (ll i=1;i<=m;++i) if (q[i].opt==1) t.add(q[i].x,q[i].y,-1); solve(1,cnt,-inf,inf); for (ll i=1;i<=m;++i) if (tag[i]) printf("%lld\n",ans[i]); }
以上是关于BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分的主要内容,如果未能解决你的问题,请参考以下文章