列隊題解以及注意事項
阿新 • • 發佈:2018-11-01
一道十分interesting的題目
這道題顯然要使用資料結構維護。但是n的規模十分大。我們便可以開n棵線段樹,動態開點。但是最後一列比較特殊,所以我們再開一棵線段樹維護最後一列。至於怎麼操作?我們考慮權值線段樹。權值線段樹一般是維護:權值為[L,r]的數有多少是滿足某種條件的。本道題目中我們維護區間[L,R]中有多少個數沒有操作過。線段樹的長度要開為 max(n,m)+q,這樣如果我們查詢一個數的位置發現她超過了m,說明她已經不在原位置了,出去的數我們用vector儲存,每次直接訪問下標就可以查詢了。這裡的原理就是查詢該行排名為k的點。發現這個點之後就將其壓入維護最後一列的vector中,並將此時在最後一列中排名為K的點壓入改行,就行了。注意特判詢問的縱座標為m的情況
code:
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> #include<cmath> #include<set> #include<cstring> #include<vector> #define max MAX #define maxn 5000006 #define mod 1000000007 #define rep(i,a,b) for (int i=a;i<=b;++i) #define erep(i,a) for (int i=head[a];i!=-1;i=e[i].next) #define half (l+r)>>1 #define lson t[s].lc #define pb push_back #define all (zmd) #define rson t[s].rc using namespace std; #define int long long struct zmd { int fx,fy; }; struct hzw { int lc,rc,sum; }t[maxn]; int n,m,mx,tot,q; inline int MAX(int a,int b) {return a>b?a:b;} inline void update(int &s,int l,int r,int p) { if (!s) s=++tot; if (l==r) { t[s].sum++; return; } int mid=half; if (p<=mid) update(lson,l,mid,p); else update(rson,mid+1,r,p); t[s].sum=t[lson].sum+t[rson].sum; } int root[maxn]; inline int query(int s,int l,int r,int p) { if (l==r) return l; int mid = half; int tmp=(mid-l+1) - t[lson].sum; if (p<=tmp) return query(lson,l,mid,p); else return query(rson,mid+1,r,p-tmp); } vector<zmd>v[300006]; inline int solve1(int x,int y) { int now = query(root[x],1,mx,y),ans; update(root[x],1,mx,now); // take away if (now<m) { ans=m*(x-1)+now; v[n+1].pb(all{x,now}); //insert back } else { zmd wow = v[x][now-m]; ans=m*(wow.fx-1)+wow.fy; v[n+1].pb(wow); } int bk = query(root[n+1],1,mx,x); update(root[n+1],1,mx,bk); if (bk<=n) v[x].pb(all{bk,m}); //no used is insert easily else {zmd wow = v[n+1][bk-n-1];v[x].pb(wow);} //find and insert now return ans; } inline int solve2(int x,int y) // final insert { int now=query(root[n+1],1,mx,x); update(root[n+1],1,mx,now); zmd wow; if (now<=n) wow.fx=now,wow.fy=m; else wow = v[n+1][now-n-1]; v[n+1].pb(wow); return m*(wow.fx-1)+wow.fy; } #undef int int main() { #define int long long cin>>n>>m>>q; mx = max(n,m)+q; rep(i,1,q) { int a,b; scanf("%lld%lld",&a,&b); printf("%lld\n",b==m?solve2(a,b):solve1(a,b)); } return 0; }
注意事項:
define max(a,b) a>b?a:b 有時候會出玄學錯誤:例子:
看,十分玄妙,所以不要亂define了