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 MB
Submit: 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

Sample Output

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

posted @ 2018-08-15 21:03  wang9897  阅读(144)  评论(0编辑  收藏  举报