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 A1, A2, …, 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 ≤ N, Q ≤ 105

1 ≤ Ai, v ≤ 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]);  }  } 




作者:xxy