[ZOJ 2112] Dynamic Rankings [块状链表+二分答案+二分查找]

来源:互联网 发布:云计算产品有哪些 编辑:程序博客网 时间:2024/06/05 04:09

两种操作,第一种操作是求区间[i,j]的第k小数,第二种操作是修改某个值

把整个数组划分为长度为根号n(大概223)的块,每个块内排序,查询时二分答案,然后两端的块直接遍历,中间的块二分查找,复杂度根号n


#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int SIZE=223;int a[100100];int b[100100];int n,m;int find(int l,int r,int x) {if (b[l]>x) return 0;int s=l;while (l!=r) {int t=(l+r)/2+1;if (b[t]<=x) l=t;else r=t-1;}return l-s+1;}int getnum(int l,int r,int t) {int ans=0,i;for (i=l;i%SIZE!=1&&i<=r;i++) {if (a[i]<=t) ans++;}for (;i+SIZE<=r;i+=SIZE) {ans+=find(i,i+SIZE-1,t);}for (;i<=r;i++) {if (a[i]<=t) ans++;}//printf("%d %d %d %d\n",l,r,t,ans);return ans;}void print(int a[]) {for (int i=1;i<=n;i++) printf("%d ",a[i]);printf("\n");}int main() {int tt,x,y,z,i;char c;scanf("%d",&tt);while (tt--) {scanf("%d%d",&n,&m);for (i=1;i<=n;i++) {scanf("%d",&a[i]);b[i]=a[i];}for (i=1;i<=n;i+=SIZE) {sort(b+i,b+min(i+SIZE,n+1));}//print(a);//print(b);for (i=0;i<m;i++) {scanf(" %c",&c);if (c=='Q') {scanf("%d%d%d",&x,&y,&z);int l=0,r=1000000100;while (l!=r) {int t=(l+r)/2;if (getnum(x,y,t)<z) l=t+1;else r=t;}printf("%d\n",l);} else {scanf("%d%d",&x,&y);a[x]=y;int l=x,r=x;for (;l%SIZE!=1;l--);for (;r%SIZE!=0&&r<n;r++);for (int j=l;j<=r;j++) b[j]=a[j];sort(b+l,b+r+1);}//print(a);//print(b);}}return 0;}


0 0
原创粉丝点击