您的位置:首页 > 其它

【COGS257】动态排名系统

2015-04-08 20:03 274 查看
[问题描述]

给定一个长度为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<

[code]//AC code by CreationAugust
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010
#define MAXINT 0x7fffffff
#define lowbit(x) x&-x
using 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]);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: