1. 程式人生 > >BZOJ3110:[Zjoi2013]K大數查詢——題解

BZOJ3110:[Zjoi2013]K大數查詢——題解

line href sdi type bzoj3110 return target getch gpo

+++++++++++++++++++++++++++++++++++++++++++

+本文作者: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 c

Output

輸出每個詢問的結果

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; }

BZOJ3110:[Zjoi2013]K大數查詢——題解