ZOJ 2112 Dynamic Rankings(块状链表)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112

题意:给出一个数列,两种操作:

(1)Q x y K,询问区间[x,y]中第K小的数;

(2)C x K,将第x个数字改为K。

思路:块状链表,每块存储250个数字,查询时二分查找;修改时插入排序。

 

 



 

 

 const int INF=1000000000;

 const int size=250;  //每块的大小

 const int MAX=50005;

 

 struct Chunk_list

 {

     int p[MAX/size+1][size],a[MAX];

     

     void input(int n)

     {

         int i;

         for(i=0;i<n;i++)

         {

             scanf("%d",&a[i]);

             p[i/size][i%size]=a[i];

         }

          for(i=0;i<n/size;i++) sort(p[i],p[i]+size);

     }

 

     //返回第d块中等于k的数字的位置

     int getpos(int d,int k)

     {

         int low=0,high=size-1,mid;

         while(low<=high)

         {

             mid=(low+high)>>1;

             if(p[d][mid]==k) break;

             if(p[d][mid]<k) low=mid+1;

             else high=mid-1;

         }

         return mid;

     }

     

     

     //返回区间[x,y]中小于等于k的数字的个数

     int getcount(int x,int y,int k)

     {

         int ans=0,low,high,mid;

         while(x%size&&x<=y)

         {

             if(a[x]<=k) ans++;

             x++;

         }

         while((y+1)%size&&x<=y)

         {

             if(a[y]<=k) ans++;

             y--;

         }

         if(x>y) return ans;

         x/=size;

         y/=size;

         while(x<=y)

         {

             low=0;

             high=size-1;

             while(low<high)

             {

                 mid=(low+high+1)>>1;

                 if(p[x][mid]<=k) low=mid;

                 else high=mid-1;

             }

             if(p[x][low]<=k) ans+=low+1;

             else ans+=low;

             x++;

         }

         return ans;

     }

 

     //返回区间[x,y]中第k小的数字

     int find(int x,int y,int k)

     {

         int low,high,mid;

         low=0;high=INF;

         while(low<high)

         {

             mid=(low+high+1)>>1;

             if(getcount(x,y,mid)>=k) high=mid-1;

             else low=mid;

         }

         return high+1;

     }

     

     //将x位置上的数字改为k

     void modify(int x,int k)

     {

         int d=x/size;

         int y=getpos(d,a[x]);

         while(y+1<size&&k>p[d][y+1])

         {

             p[d][y]=p[d][y+1];

             y++;

         }

         while(y-1>=0&&k<p[d][y-1])

         {

             p[d][y]=p[d][y-1];

             y--;

         }

         p[d][y]=a[x]=k;

     }

 };

 

 

 Chunk_list a;

 int C,n,m;

 

 int main()

 {

     for(scanf("%d",&C);C--;)

     {

         scanf("%d%d",&n,&m);

         a.input(n);

         int x,y,k;

         char cmd[5];

         while(m--)

         {

             scanf("%s",cmd);

             if(cmd[0]=='Q')

             {

                 scanf("%d%d%d",&x,&y,&k);

                 printf("%d\n",a.find(x-1,y-1,k));

             }

             else

             {

                 scanf("%d%d",&x,&k);

                 a.modify(x-1,k);

             }

         }

     }

     return 0;

 }

 

  

 

你可能感兴趣的:(dynamic)