【NOIP2017DAY2T3 【NOIP2017提高组正式赛】列队 】(动态开点+n棵线段树)

来源:互联网 发布:linux翻墙工具 编辑:程序博客网 时间:2024/06/06 00:55

Link

https://jzoj.net/senior/#main/show/5478

Problem

给定一个NM的矩阵,有Q个形如(x,y)的询问当前矩阵里(x,y)点的值.

初始(x,y)点的值为(x1)M+y.

询问一次后(x,y)号点右边的点往左移,最后一列的点往上移,再把(x,y)移到(N,M)

Solution

这题的N,M,Q比较大

考虑用线段树.

我们可以动态开点,建立n+1棵独立的线段树

即每一行对应一颗,最后一列单独一颗.

仔细想想,就可以实现上述操作,实现也并不复杂,不过一定要注意空间,注意常数.

#include <iostream>#include <cstdio>#include <cstring>#define ll long long#define fo(i,a,b) for(i=a;i<=b;i++)#define Maxn 300010#define Mlen 6000010using namespace std;ll n,m,q,i,x[Maxn],y[Maxn],len[Maxn],lem,cnt,ans,temp,sans;ll lef[Mlen],righ[Mlen],pl[Mlen],pr[Mlen],tree[Mlen],anstree[Mlen];ll p[Maxn],xx[Maxn];bool bz[Mlen][2];void bulidleft(ll x){if (!bz[x][0]) bz[x][0]=true, pl[x]=++cnt, lef[cnt]=lef[x], righ[cnt]=(righ[x]+lef[x])>>1;}void bulidrigh(ll x){if (!bz[x][1]) bz[x][1]=true, pr[x]=++cnt, lef[cnt]=((righ[x]+lef[x])>>1)+1, righ[cnt]=righ[x];}void pos(ll x,ll st,ll en,ll p,ll xx,ll yy){    ll len=righ[x]+lef[x];    if (st==en)    {        if (xx==-1) anstree[x]=yy; else        {            if (anstree[x]!=0) sans=anstree[x]; else            if (xx==0) sans=(righ[x]-1)*m+yy; else sans=(xx-1)*m+righ[x];            tree[x]++;        }        return;    }    if (xx==-1){ if((len>>1)>=p) bulidleft(x), pos(pl[x],lef[pl[x]],righ[pl[x]],p,xx,yy); else bulidrigh(x), pos(pr[x],lef[pr[x]],righ[pr[x]],p,xx,yy); }    else{        ll sum=((len>>1)-lef[x]+1)-tree[pl[x]];        if (sum>=p) bulidleft(x), pos(pl[x],lef[pl[x]],righ[pl[x]],p,xx,yy); else bulidrigh(x), pos(pr[x],lef[pr[x]],righ[pr[x]],p-sum,xx,yy);      }    tree[x]=tree[pl[x]]+tree[pr[x]];}int main(){    freopen("phalanx.in","r",stdin),freopen("phalanx.out","w",stdout);    scanf("%lld%lld%lld",&n,&m,&q), lem=n+q;    fo(i,1,n) len[i]=m;    fo(i,1,q)        scanf("%lld%lld",&x[i],&y[i]), len[x[i]]++;    fo(i,1,n) lef[++cnt]=1, righ[cnt]=len[i], p[i]=cnt, xx[i]=m-1;    lef[++cnt]=1, righ[cnt]=lem, p[n+1]=cnt, xx[n+1]=n;    fo(i,1,q){        ++xx[n+1];        if (y[i]==m){ pos(p[n+1],1,lem,x[i],0,m), pos(p[n+1],1,lem,xx[n+1],-1,sans), printf("%lld\n",sans); continue; }        xx[x[i]]++, pos(p[x[i]],1,len[x[i]],y[i],x[i],0), printf("%lld\n",sans), temp=sans, pos(p[n+1],1,lem,x[i],0,m), pos(p[x[i]],1,len[x[i]],xx[x[i]],-1,sans), pos(p[n+1],1,lem,xx[n+1],-1,temp);    }}
原创粉丝点击