P3332 [ZJOI2013]K大数查询
题目描述
详见:P3332 [ZJOI2013]K大数查询
solution
整体二分+树状数组
code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+50;
typedef long long ll;
ll n,m,Ans[MAXN],id[MAXN],quel[MAXN],quer[MAXN],f[MAXN];inline ll read()
{ll x=0,f=1; char c=getchar();while (c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
struct anode{ll id,opt,l,r,x,color; } a[MAXN];
int comparex(anode x,anode y) { return (x.opt<y.opt)||(x.opt==y.opt&&x.x<y.x); }
int compareid(anode x,anode y) { return x.id<y.id; }
struct Tree_Array
{ll tree[2][MAXN<<1];int lowbit(int x){ return x&(-x); }ll getans(int opt,ll x) { ll ans=0; while (x) ans+=tree[opt][x],x-=lowbit(x); return ans; }ll query(int l,int r) { return getans(0,r)*(r+1)-getans(0,l)*l-getans(1,r)+getans(1,l); }void change(int opt,int x,ll y) { while (x<=n) tree[opt][x]+=y,x+=lowbit(x); }void update(int l,int r,ll x) { change(0,l,x),change(1,l,x*l),change(0,r+1,-x),change(1,r+1,-x*(r+1)); }
} Tree;
void solve(int L,int R,int l,int r)
{if (l>r) return; /*cout<<L<<" "<<R<<" "<<l<<" "<<r<<":";for (int i=l;i<=r;i++) cout<<" "<<id[i]; cout<<endl;*/if (L==R){for (int i=l;i<=r;i++) Ans[id[i]]=L;return;}int mid=(L+R)>>1,numl=0,numr=0;for (int i=l;i<=r;i++){if (a[id[i]].opt==1){if (a[id[i]].color<=mid) quel[++numl]=id[i],Tree.update(a[id[i]].l,a[id[i]].r,1);else quer[++numr]=id[i];}else{ll q=Tree.query(a[id[i]].l,a[id[i]].r);if (q>=a[id[i]].color) quel[++numl]=id[i];else quer[++numr]=id[i],a[id[i]].color-=q;}}for (int i=1;i<=numl;i++) if (a[quel[i]].opt==1) Tree.update(a[quel[i]].l,a[quel[i]].r,-1);for (int i=l;i<=l+numl-1;i++) id[i]=quel[i-l+1];for (int i=r-numr+1;i<=r;i++) id[i]=quer[i-r+numr];solve(L,mid,l,l+numl-1);solve(mid+1,R,r-numr+1,r);
}
int main()
{n=read(),m=read();ll p=0;for (int i=1;i<=m;i++) a[i]=(anode){i,read(),read(),read(),read(),0},id[i]=i;sort(a+1,a+m+1,comparex);a[0].x=a[1].x+1;for (int i=1;i<=m;i++) if (a[i].opt==1) a[i].color=a[i-1].color+(a[i].x!=a[i-1].x),p=max(p,a[i].color);else a[i].color=a[i].x;for (int i=1;i<=m;i++)if (a[i].opt==1) a[i].color=p-a[i].color+1,f[a[i].color]=a[i].x;sort(a+1,a+m+1,compareid);/*cout<<endl;for (int i=1;i<=m;i++) cout<<a[i].opt<<" "<<a[i].l<<" "<<a[i].r<<" "<<a[i].color<<endl;cout<<endl;*/solve(1,n*2+1,1,m);for (int i=1;i<=m;i++)if (a[i].opt==2) printf("%lld\n",f[Ans[i]]);return 0;
}
/*
5 4
1 1 5 1
1 1 2 3
1 2 4 5
2 1 3 21
2
1
*/