BZOJ3110:[ZJOI2013]K大数查询——题解
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
http://www.lydsy.com/JudgeOnline/problem.php?id=3110
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b cOutput
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
整体二分板子题,具体题解百度去吧,2333333……
#include<algorithm> #include<iostream> #include<cstring> #include<cctype> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; const int N=100010; inline ll read(){ ll X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int op[N],a[N],b[N],pos[N],ans[N]; ll c[N],tree[2][N]; int n,m,tot; int tmp1[N],tmp2[N]; inline int lowbit(int t){return t&(-t);} void clear(int k,int x){ for(int i=x;i<=tot;i+=lowbit(i))tree[k][i]=0; } void add(int k,int x,ll y){//将a[x]+y for(int i=x;i<=tot;i+=lowbit(i))tree[k][i]+=y; } void modify(ll x,ll y,ll z){ add(0,x,z);add(1,x,z*(x-1));add(0,y+1,-z);add(1,y+1,-z*y); } ll query(int k,int x){//1-x区间和 ll res=0; for(int i=x;i>0;i-=lowbit(i))res+=tree[k][i]; return res; } ll qry(ll x,ll y){ return query(0,y)*y-query(1,y)-query(0,x-1)*(x-1)+query(1,x-1); } void solve(int L,int R,int l,int r){ if(L>R)return; if(l==r){ for(int i=L;i<=R;i++){ if(op[pos[i]]==2)ans[pos[i]]=l; } return; } int idx1=0,idx2=0,mid=(l+r)>>1; for(int i=L;i<=R;i++){ if(op[pos[i]]==1){ if((int)c[pos[i]]<=mid){ modify(a[pos[i]],b[pos[i]],1); tmp1[idx1++]=pos[i]; }else tmp2[idx2++]=pos[i]; }else{ ll tmp=qry(a[pos[i]],b[pos[i]]); if(tmp<c[pos[i]]){ tmp2[idx2++]=pos[i]; c[pos[i]]-=tmp; } else tmp1[idx1++]=pos[i]; } } for(int i=0;i<idx1;i++){ int k=tmp1[i]; clear(0,a[k]);clear(1,a[k]); clear(0,b[k]+1);clear(1,b[k]+1); } int MID=L+idx1; for(int i=L;i<MID;i++)pos[i]=tmp1[i-L]; for(int i=MID;i<=R;i++)pos[i]=tmp2[i-MID]; solve(L,MID-1,l,mid);solve(MID,R,mid+1,r); return; } int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ op[i]=read(); a[i]=read();b[i]=read();c[i]=read(); if(op[i]==1){c[i]=(ll)n-c[i]+1;tot=max(tot,(int)c[i]);} pos[i]=i; } solve(1,m,1,tot); for(int i=1;i<=m;i++){ if(op[i]==2)printf("%d\n",n-ans[i]+1); } return 0; }