1. 程式人生 > >【線段樹】【資料結構】NOIP2017列隊

【線段樹】【資料結構】NOIP2017列隊

分析:

很簡單的線段樹水題。。。不知道為啥一年前不會。。。
每行開一個線段樹,最後一列再開一個線段樹。

對每個操作分兩種情況討論:在最後一列,不在最後一列。

如果在最後一列,那麼線上段樹上把那個位置刪去,然後末尾插入它。

如果不在最後一列,現在行線段樹上把那個位置刪去,在列線段樹末尾插入它。並且找到列線段樹對應的行的值,把他從列線段樹中刪除,加入到行線段樹中去。

用動態加點的方式可以避免TLE和MLE

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define
SF scanf
#define PF printf #define MAXN 15000100 using namespace std; void Read(int &x){ char c; while(c=getchar(),c!=EOF&&(c<'0'||c>'9')); x=c-'0'; while(c=getchar(),c!=EOF&&c>='0'&&c<='9') x=x*10+c-'0'; } typedef long long ll; int n,m,q,cnt; int
tree[MAXN]; ll val[MAXN]; int tag[MAXN]; int ls[MAXN],rs[MAXN]; void pushdown(int x,int l,int r){ if(tag[x]==0) return ; if(ls[x]==0) ls[x]=++cnt; if(rs[x]==0) rs[x]=++cnt; tag[ls[x]]+=tag[x]; tag[rs[x]]+=tag[x]; int mid=(l+r)>>1; tree[ls[x]]+=
tag[x]*(mid-l+1); tree[rs[x]]+=tag[x]*(r-mid); tag[x]=0; } void add(int id,int l,int r,int pl,int pr,int val){ if(l!=r) pushdown(id,l,r); if(l>=pl&&r<=pr){ tag[id]+=val; tree[id]+=(r-l+1)*val; return ; } int mid=(l+r)>>1; if(pl<=mid){ if(ls[id]==0) ls[id]=++cnt; add(ls[id],l,mid,pl,pr,val); } if(pr>mid){ if(rs[id]==0) rs[id]=++cnt; add(rs[id],mid+1,r,pl,pr,val); } tree[id]=tree[ls[id]]+tree[rs[id]]; } pair<ll,int> que(int id,int l,int r,int k){ if(l!=r) pushdown(id,l,r); if(l==r){ if(val[id]==0) return make_pair(l,l); else return make_pair(val[id],l); } int mid=(l+r)>>1; if(tree[ls[id]]>=k){ if(ls[id]==0) ls[id]=++cnt; return que(ls[id],l,mid,k); } else{ if(rs[id]==0) rs[id]=++cnt; return que(rs[id],mid+1,r,k-tree[ls[id]]); } } void addval(int id,int l,int r,int pos,ll v){ if(l!=r) pushdown(id,l,r); if(l==r){ val[id]=v; tree[id]=1; tag[id]=0; return ; } int mid=(l+r)>>1; if(pos<=mid){ if(ls[id]==0) ls[id]=++cnt; addval(ls[id],l,mid,pos,v); } else{ if(rs[id]==0) rs[id]=++cnt; addval(rs[id],mid+1,r,pos,v); } tree[id]=tree[ls[id]]+tree[rs[id]]; } int len[MAXN]; int main(){ SF("%d%d%d",&n,&m,&q); cnt=n+1; int l=1,r=m+q-1; for(int i=1;i<=n;i++){ add(i,l,r,1,m-1,1); len[i]=m-1; } add(n+1,1,n+q,1,n,1); len[n+1]=n; int x,y; for(int i=1;i<=q;i++){ Read(x),Read(y); if(y==m){ pair<ll,int> res=que(n+1,1,n+q,x); if(res.second<=n) res.first*=m; ll delx=res.first; PF("%lld\n",delx); add(n+1,1,n+q,res.second,res.second,-1); len[n+1]++; addval(n+1,1,n+q,len[n+1],delx); } else{ pair<ll,int> res1=que(x,l,r,y); if(res1.second<=m-1) res1.first=res1.first+1ll*(x-1)*m; ll delx=res1.first; PF("%lld\n",delx); pair<ll,int> res2=que(n+1,1,n+q,x); if(res2.second<=n) res2.first*=m; ll nx=res2.first; add(x,l,r,res1.second,res1.second,-1); len[x]++; addval(x,l,r,len[x],nx); add(n+1,1,n+q,res2.second,res2.second,-1); len[n+1]++; addval(n+1,1,n+q,len[n+1],delx); } } }