hdu 5412 CRB and Queries(整体二分)

CRB and Queries

http://acm.hdu.edu.cn/showproblem.php?pid=5412

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description
There are N boys in CodeLand.
Boy i has his coding skill Ai.
CRB wants to know who has the suitable coding skill.
So you should treat the following two types of queries.
Query 1: 1 l v
The coding skill of Boy l has changed to v.
Query 2: 2 l r k
This is a report query which asks the k-th smallest value of coding skill between Boy l and Boy r(both inclusive).
 
Input
There are multiple test cases. 
The first line contains a single integer N.
Next line contains N space separated integers A1A2, …, AN, where Ai denotes initial coding skill of Boy i.
Next line contains a single integer Q representing the number of queries.
Next Q lines contain queries which can be any of the two types.
1 ≤ NQ ≤ 105
1 ≤ Aiv ≤ 109
1 ≤ l ≤ r ≤ N
1 ≤ k ≤ r  l + 1

Output
For each query of type 2, output a single integer corresponding to the answer in a single line.
 
Sample Input
5
1 2 3 4 5
3
2 2 4 2
1 3 6
2 2 4 2
 
Sample Output
3 4
 题意:询问区间第k值(小),支持修改操作
整体二分+树状数组
本题与上题不同处在于这里要多组数据输入
 
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100001
int n,m,tot,t;
int ans[N*2],a[N],k[N*3];
int c[N];
struct node
{
	int posx,posy,key,kind,bl,cur;
}q[N*3],tmp1[N*3],tmp2[N*3];
int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int y)
{
	while(x<=n)
	{
		c[x]+=y;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int b=0;
	while(x)
	{
		b+=c[x];
		x-=lowbit(x);
	}
	return b;
}
void solve(int head,int tail,int l,int r)
{
	if(head>tail) return;
	if(l==r)
	{
		for(int i=head;i<=tail;i++) 
		 if(q[i].kind==3) ans[q[i].bl]=l;
		return;
	}
	int mid=l+r>>1;
	for(int i=head;i<=tail;i++)
	{
		if(q[i].kind==1&&q[i].key<=mid) add(q[i].posx,-1);
		else if(q[i].kind==2&&q[i].key<=mid) add(q[i].posx,1);
		else if(q[i].kind==3) k[i]=sum(q[i].posy)-sum(q[i].posx-1);
	}
	for(int i=head;i<=tail;i++)
	{
		if(q[i].kind==1&&q[i].key<=mid) add(q[i].posx,1);
		else if(q[i].kind==2&&q[i].key<=mid) add(q[i].posx,-1);
	}
	int ll=0,rr=0;
	for(int i=head;i<=tail;i++)
	{
		if(q[i].kind==3)
		{
			if(q[i].cur+k[i]>=q[i].key) tmp1[++ll]=q[i];
			else 
			{
				q[i].cur+=k[i];
				tmp2[++rr]=q[i];
			}
		}
		else
		{
			if(q[i].key<=mid) tmp1[++ll]=q[i];
			else tmp2[++rr]=q[i];
		}
	}
	for(int i=1;i<=ll;i++) q[head+i-1]=tmp1[i];
	for(int i=1;i<=rr;i++) q[head+ll+i-1]=tmp2[i];
	solve(head,head+ll-1,l,mid);solve(head+ll,tail,mid+1,r);
}
void pre()
{
	tot=t=0;
	memset(c,0,sizeof(c));
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		pre();
		int x,y,z;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			q[++tot]=(node){i,0,x,2};
			a[i]=x;
		}
		scanf("%d",&m); 
		int h;
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&h);
			if(h==2) 
			{
				scanf("%d%d%d",&x,&y,&z);
				q[++tot]=(node){x,y,z,3,++t,0};
			}
			else 
			{
				scanf("%d%d",&x,&z);
				q[++tot]=(node){x,0,a[x],1,0,0};
				q[++tot]=(node){x,0,z,2,0,0};
				a[x]=z;
			}
		}
		solve(1,tot,0,1e9);
		for(int i=1;i<=t;i++) printf("%d\n",ans[i]);
	}

}

  

posted @ 2017-03-14 21:22  TRTTG  阅读(271)  评论(0编辑  收藏  举报