「NOIP2017」列队 //线段树

「NOIP2017」列队
放loj的题面好啦


题意

有一个n行m列的方阵,第i行j列的点编号为(i-1)m+j。
给出q次操作,每次把第x行y列的点拿出来,然后把这一行它之后的点都向左推,把最后一列x行之后的点都向上推,然后把之前(x,y)的点放到最后一个位置,询问这个点的编号。


题解

//树状数组的做法我不会呀 写一写暴力一些的做法吧
维护每一行和最后一列,于是需要实现的操作就变成了找到并删掉第k个数、把一个数插到末尾。
这东西是不是随便套个数据结构就好啦?
我写了个动态开点的线段树不会别的 空间上来看是比较劣…不过512M就可以乱开了
初始状态怎么办呢…打一个等差数列的标记就好了


代码

#include
#define V 15000000
#define N 300005
#define New(w) (w=(w?w:++cnt))
using namespace std;
typedef long long ll;
char ch;
inline void rd(int &x)
{
    x=0;
    do ch=getchar();
    while(ch<'0'||ch>'9');
    do x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    while(ch>='0'&&ch<='9');
}
bool flag;
int n,m,q,Rt,cnt,L,x,y,
sz[V],c[V][2],rt[N],mx[V];
ll st[V],ans,tp;
inline void pd(int x,int l,int r,int mid)
{
    if(!st[x])return;
    sz[New(c[x][0])]=mx[c[x][0]]=mid-l+1;
    st[c[x][0]]=st[x];
    sz[New(c[x][1])]=mx[c[x][1]]=r-mid+1;
    st[c[x][1]]=st[x]+(ll)(mid-l+1)*(flag?m:1);
    st[x]=0;
}
void build(int &x,int l,int r,int r_,ll fr)
{
    sz[New(x)]=r_-l+1,mx[x]=r_-l+1;
    if(r==r_)
    {st[x]=fr;return;}
    int mid=l+r>>1;
    if(r_>mid)build(c[x][1],mid+1,r,r_,fr+(ll)(mid-l+1)*(flag?m:1));
    build(c[x][0],l,mid,r_int mid;
void ins(int &x,int l,int r,ll val)
{
    if(l==r)
    {sz[New(x)]++,mx[x]++,st[x]=val;return;}
    mid=l+r>>1,sz[New(x)]++,mx[x]++;
    pd(x,l,r,mid);
    if(mx[c[x][0]]1)
    ins(c[x][0],l,mid,val);
    else ins(c[x][1],mid+1,r,val);
}
ll qry(int &x,int l,int r,int loc)
{
    sz[New(x)]--;
    if(l==r)return st[x];
    mid=l+r>>1;
    pd(x,l,r,mid);
    return (loc>sz[c[x][0]])?qry(c[x][1],mid+1,r,
    loc-sz[c[x][0]]):qry(c[x][0],l,mid,loc);
}
int main()
{
    rd(n),rd(m),rd(q);
    L=max(n,m)+q;
    for(int i=1;i<=n;i++)
    build(rt[i],1,L,m-1,(ll)(i-1)*m+1);
    flag=1,build(Rt,1,L,n,m);
    while(q--)
    {
        rd(x),rd(y);
        if(y^m)
        flag=0,printf("%lld\n",ans=qry(rt[x],1,L,y)),
        flag=1,tp=qry(Rt,1,L,x),
        ins(Rt,1,L,ans),
        flag=0,ins(rt[x],1,L,tp);
        else
        flag=1,printf("%lld\n",ans=qry(Rt,1,L,x)),
        ins(Rt,1,L,ans);
    }
}

你可能感兴趣的:(线段树)