1. 程式人生 > >洛谷P3960 列隊 NOIp2017 線段樹/樹狀數組/splay

洛谷P3960 列隊 NOIp2017 線段樹/樹狀數組/splay

結果 nbsp spl pan 空間 reg push else lin

正解:動態開點線段樹

解題報告:

傳送門!

因為最近學主席樹的時候順便get到了動態開點線段樹?剛好想起來很久很久以前就想做結果一直麻油做的這題,,,所以就做下好了QAQ

然後說下,這題有很多種方法,我目前是先只寫個最傻逼的方法,等學了splay什麽的再來upd一下QAQ(這題好像有,線段樹.樹狀數組.splay等各種方法,我可能都會寫只要我麻油咕QAQ

然後就直接進入正題QAQ

首先其實要知道動態開點線段樹線段樹思想什麽的都是一樣兒的,只是實現方法有一點兒區別(就是動態開點線段樹節省點兒空間而已QAQ

所以就考慮線段樹怎麽做昂QAQ

首先可以發現,每次變動之後,有影響的只會是這個點,這一行,最後一列,對趴

所以可以考慮對每一行(不包括最後一個點QAQ)以及最後一列分別開個線段樹

然後每次對當前操作(x,y),先記錄ans,並把這個編號從x這一行的線段樹中刪去,加入第n+1棵的最後一個位置,然後把第n+1棵的x位置加入到第x行的最後一個位置

然後註意以下如果x=n也就是說它本來就在最後一列的時候就不用管了QAQ

然後關於動態開點,我提下QAQ

考慮q的範圍,即最多有q個點加入,那麽線段樹的長度最長為 max(n,m)+q

然後考慮到nmq範圍,所以動態開點,over

然後再說一個方法,其實也是動態開點線段樹,只是還要簡單點兒,因為它還開了個vector

然後有vector的話就每次壓進去就好了鴨,就是說線段樹是個權值線段樹

記錄被修改後的數字的,具體的值在vector中查詢一下就好

具體看代碼QAQ

然後記得開ll,,,我也不知道我什麽豬腦子開了個int然後還麻油發現有什麽不對,,,我都佩服我自己了QAQ

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define rg register
#define gc getchar()
#define int long long
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)

const
int N=3e5+100,M=1e7+1000; int n,m,q,rt[N],nod_cnt,mx; struct sgtr{int ls,rs,sz;}tr[M]; vector<int>v[N]; il int read() { rg char ch=gc;rg int x=0;rg bool y=1; while(ch!=- && (ch>9 || ch<0))ch=gc; if(ch==-)ch=gc,y=0; while(ch>=0 && ch<=9)x=(x<<1)+(x<<3)+(ch^0),ch=gc; return y?x:-x; } il void modify(int &nw,int l,int r,int to) { if(!nw)nw=++nod_cnt;++tr[nw].sz;if(l==r)return; int mid=(l+r)>>1; if(to<=mid)modify(tr[nw].ls,l,mid,to);else modify(tr[nw].rs,mid+1,r,to); } il int query(int nw,int l,int r,int to) { if(l==r)return l;int mid=(l+r)>>1,tmp=mid-l+1-tr[tr[nw].ls].sz; if(to<=tmp)return query(tr[nw].ls,l,mid,to);return query(tr[nw].rs,mid+1,r,to-tmp); } il int wk1(int x,int y) { int pos=query(rt[n+1],1,mx,x);modify(rt[n+1],1,mx,pos); int ans=(pos<=n?1ll*pos*m:v[n+1][pos-n-1]); return v[n+1].push_back(y?y:ans),ans; } il int wk2(int x,int y) { int pos=query(rt[x],1,mx,y);modify(rt[x],1,mx,pos); int ans=(pos<m?1ll*(x-1)*m+pos:v[x][pos-m]); return v[x].push_back(wk1(x,ans)),ans; } main() { // freopen("ld.in","r",stdin);freopen("ld.out","w",stdout); n=read();m=read();q=read();mx=max(n,m)+q; while(q--){int x=read(),y=read();printf("%lld\n",(y==m?wk1(x,0):wk2(x,y)));} return 0; }
先放下開vector做的代碼QAQ(然後不開vector的代碼可能就咕了QAQ?

洛谷P3960 列隊 NOIp2017 線段樹/樹狀數組/splay