BZOJ3110: [Zjoi2013]K大数查询
题解:整体二分答案即可
#include <bits/stdc++.h> #define ll long long const int MAXN=5e4+10; using namespace std; ll sum1[MAXN],sum2[MAXN]; int n,m; vector<int>vec; int get_id(int x){return x&(-x);} void update1(int x,ll vul){ if(!x)return ; for(int i=x;i>0;i-=get_id(i))sum1[i]+=vul; } ll Sum1(int x){ if(!x)return 0; ll ans=0; for(int i=x;i<=n;i+=get_id(i))ans+=sum1[i]; return ans; } void update2(int x,ll vul){ if(!x)return ; for(int i=x;i<=n;i+=get_id(i))sum2[i]+=vul; } ll Sum2(int x){ if(!x)return 0; ll ans=0; for(int i=x;i>0;i-=get_id(i))ans+=sum2[i]; return ans; } typedef struct node{ int op,l,r;ll c,cnt,ans; }node; node que[MAXN]; int id[MAXN],ed[MAXN],ip[MAXN]; void update(int t){ update2(que[t].r,que[t].r);update1(que[t].r-1,1); update2(que[t].l,1-que[t].l);update1(que[t].l-1,-1); } void clear(int t){ update2(que[t].r,-1*que[t].r);update1(que[t].r-1,-1); update2(que[t].l,que[t].l-1);update1(que[t].l-1,1); } ll querty(int t){ ll ans=0;ans+=Sum2(que[t].r)+1LL*que[t].r*Sum1(que[t].r); ans-=(Sum2(que[t].l-1)+1LL*(que[t].l-1)*Sum1(que[t].l-1)); return ans; } int flag=0; void slove(int ql,int qr,int l,int r){ if(ql>qr||l>r)return ; int mid=(l+r)>>1; int cnt1=0,cnt2=0; //cout<<vec[mid-1]<<" "<<mid<<endl; for(int i=ql;i<=qr;i++){ if(que[id[i]].op==1){ if(que[id[i]].c>=vec[mid-1])ip[++cnt1]=id[i],update(id[i]); else ed[++cnt2]=id[i]; } else{ //cout<<querty(id[i])<<" "<<que[id[i]].cnt<<" "<<que[id[i]].c<<" "<<id[i]<<endl; if(querty(id[i])+que[id[i]].cnt>=que[id[i]].c)ip[++cnt1]=id[i],que[id[i]].ans=vec[mid-1]; else ed[++cnt2]=id[i],que[id[i]].cnt+=querty(id[i]); } } //if(flag==2)cout<<cnt2<<" "<<cnt1<<" "<<mid<<endl; //flag++; for(int i=ql;i<=qr;i++){if(que[id[i]].op==1&&que[id[i]].c>=vec[mid-1])clear(id[i]);} //for(int i=1;i<=n;i++)sum1[i]=sum2[i]=0; for(int i=1;i<=cnt2;i++)id[ql+i-1]=ed[i]; for(int i=1;i<=cnt1;i++)id[ql+cnt2+i-1]=ip[i]; slove(ql,ql+cnt2-1,l,mid-1); slove(ql+cnt2,qr,mid+1,r); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d%lld",&que[i].op,&que[i].l,&que[i].r,&que[i].c),id[i]=i,que[i].cnt=0; if(que[i].op==1)vec.push_back(que[i].c); } sort(vec.begin(),vec.end()); int sz=unique(vec.begin(),vec.end())-vec.begin(); slove(1,m,1,sz); for(int i=1;i<=m;i++){ if(que[i].op==2)printf("%lld\n",que[i].ans); } }
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 11674 Solved: 3512
[Submit][Status][Discuss]
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
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
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint