zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
    	}
    
    }
    

      

  • 相关阅读:
    【转载wpf命令】
    【转载WPF资源】
    【转载MVVM模式的简介】
    【转载有关XmlAttribute的知识】
    【test7】stream、用于输入和输出的类、特性
    【补充作业】XML和LINQ
    CodeVS 1084 乒乓球
    android开发之屏幕旋转
    Android开发之新建项目报错的问题
    Android 开发获取用户权限
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6550777.html
Copyright © 2011-2022 走看看