Death Sequence HDU

来源:互联网 发布:音频裁切软件 编辑:程序博客网 时间:2024/05/17 01:25

用线段树去模拟,开始每点的值为1,单点查询相对位置,然后用vis数组记录结果,将该点的值置0。
比如,我查第一个删除的点的相对位置为1,然后线段树找了了val[i]=1的位置,然后将该点置为0,删除下一个点的时候,相对位置就是k+1-1(因为前面已经删了一个了),然后用线段树找,再下一个点的时候相对位置就是k*2+1-2;

然后如果相对位置temp小于等于左边的val,就往左走,否则就往右走,temp=temp-val[i<<1];

时间复杂度为 : O(nlogn)

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int maxn = 3000000+10;int vis[maxn];int val[maxn<<2];void build(int i,int l,int r){    val[i]=0;    if(l==r)    {        val[i]=1;        vis[l]=0;        return ;    }    int mid=(l+r)>>1;    build(i<<1,l,mid);    build(i<<1|1,mid+1,r);    val[i]=val[i<<1]+val[i<<1|1];}int h=1;void sert(int i,int l,int r,int temp){    if(l==r)    {        vis[h++]=l;        val[i]=0;        return ;    }    int mid=(l+r)>>1;    if(temp<=val[i<<1]) sert(i<<1,l,mid,temp);    else {        sert(i<<1|1,mid+1,r,temp-val[i<<1]);    }    val[i]=val[i<<1]+val[i<<1|1];}int main(){   // freopen("E:\\input.txt","r",stdin);    int T;    scanf("%d",&T);    while(T--)    {        memset(vis,0,sizeof(vis));        memset(val,0,sizeof(val));        int n,k,q;        scanf("%d %d %d",&n,&k,&q);        build(1,1,n);        int i=0,t=0,num=n;        h=1;        while(num)        {            int temp=k*i+1-t;            if(temp<=num)            {                sert(1,1,n,temp);                i++;                t++;                num--;            }            else {                i=0;                t=0;            }        }        while(q--)        {            int a;            scanf("%d",&a);            printf("%d\n",vis[a]);        }    }    return 0;}
原创粉丝点击