【COGS257】动态排名系统

来源:互联网 发布:德勤财务咨询 知乎 编辑:程序博客网 时间:2024/06/05 01:22

[问题描述]
给定一个长度为N的已知序列Ai,要求维护这个序列,能够支持以下两种操作:
1、查询A[i],A[i+1],A[i+2],…,Aj中,升序排列后排名第k的数。
2、修改A[i]的值为j。

所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。

[输入格式]
第一行包含一个整数D(0<=D<=4),表示测试数据的数目。接下来有D组测试数据,每组测试数据中,首先是两个整数N(1<=N<=50000),M(1<=M<=10000),表示序列的长度为N,有M个操作。接下来的N个不大于1,000,000,000正整数,第i个表示序列A[i]的初始值。然后的M行,每行为一个操作
Q i j k 或者
C i j
分别表示查询A[i],A[i+1],A[i+2],…,Aj中,升序排列后排名第k的数,和修改A[i]的值为j。

[输出格式]
对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。

[样例输入]
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

[样例输出]
3
6
3
6
一开始线段树乱搞,写了个错误性很显然的代码交上去还以为没问题
结果就是这么显然的错误竟然能A5个点2333
后来受了启发做了两个改变就A了.
1.把修改操作在读入时拆分成两个操作,一个是删除,一个是插入(核心就是这个位置.其实线段树乱搞加上这一步也可以A的)
2.把线段树改成了树状数组简洁好看www
我的整体二分也算是写熟了>w<

//AC code by CreationAugust#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 100010#define MAXINT 0x7fffffff#define lowbit(x) x&-xusing namespace std;int T;int n,m;int ans[MAXN];int a[MAXN],last[MAXN];char ch[2];int c[MAXN];int top=0,num=0,l,r,k;struct Query{    int l,r,x,op,k;}ques[MAXN],q1[MAXN],q2[MAXN];void add(int i,int x){    while (i>0&&i<=num) c[i]+=x,i+=lowbit(i);}int sum(int l,int r){    int ret=0;    while (r>0) ret+=c[r],r-=lowbit(r);    while (l>0) ret-=c[l],l-=lowbit(l);    return ret;}void solve(int L,int R,int l,int r){    int mid=(L+R)>>1,tp1=0,tp2=0;    if (l>r) return;    if (L==R)    {        for (int i=l;i<=r;i++) if (ques[i].op==2) ans[ques[i].x]=a[mid];        return;    }    for (int i=l;i<=r;i++)    {        if (ques[i].op==1)        {            if (ques[i].k<=a[mid]) add(ques[i].l,ques[i].r),q1[++tp1]=ques[i];            else q2[++tp2]=ques[i];        }        else        {            int temp=sum(ques[i].l-1,ques[i].r);            if (ques[i].k<=temp) q1[++tp1]=ques[i];            else ques[i].k-=temp,q2[++tp2]=ques[i];        }    }    for (int i=1;i<=tp1;i++) if (q1[i].op==1) add(q1[i].l,-q1[i].r);    memcpy(ques+l,q1+1,sizeof(Query)*tp1);    memcpy(ques+l+tp1,q2+1,sizeof(Query)*tp2);    solve(L,mid,l,l+tp1-1);    solve(mid+1,R,l+tp1,r);}int main(){    freopen("dynrank.in","r",stdin);    freopen("dynrank.out","w",stdout);    scanf("%d",&T);    while (T--)    {        memset(ans,0,sizeof(ans));        Query temp[MAXN];        top=0;num=0;        scanf("%d%d",&n,&m);        for (int i=1;i<=n;i++)        {            scanf("%d",&a[++top]);last[top]=a[top];            ques[++num]=((Query){i,1,i,1,a[top]});        }        for (int i=n+1;i<=n+m;i++)        {            scanf("%s",ch);            if (ch[0]=='Q')            {                scanf("%d%d%d",&l,&r,&k);                ques[++num]=((Query){l,r,num,2,k});            }            else            {                scanf("%d%d",&l,&k);a[++top]=k;                ques[++num]=((Query){l,1,num,1,k});//将一个修改操作拆分成一个删除,一个插入                ques[++num]=((Query){l,-1,num,1,last[l]});                last[l]=k;            }        }        sort(a+1,a+top+1);        top=unique(a+1,a+top+1)-a-1;        for (int i=1;i<=num;i++) temp[i]=ques[i];        solve(1,top,1,num);         for (int i=1;i<=num;i++) if (temp[i].op!=1) printf("%d\n",ans[i]);    }}
1 0
原创粉丝点击