【線段樹】【資料結構】NOIP2017列隊
阿新 • • 發佈:2018-12-10
分析:
很簡單的線段樹水題。。。不知道為啥一年前不會。。。
每行開一個線段樹,最後一列再開一個線段樹。
對每個操作分兩種情況討論:在最後一列,不在最後一列。
如果在最後一列,那麼線上段樹上把那個位置刪去,然後末尾插入它。
如果不在最後一列,現在行線段樹上把那個位置刪去,在列線段樹末尾插入它。並且找到列線段樹對應的行的值,把他從列線段樹中刪除,加入到行線段樹中去。
用動態加點的方式可以避免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);
}
}
}