CodeForces - 1288E Messenger Simulator(树状数组)
題目鏈接:點擊查看
題目大意:給出n和m,表示n個人和m個操作,每次操作會將一個數x放到首位置上來,其他數往后順延,比如:
初始時的數組為[4,1,5,3,2],當第一個x為 3 ,則序列變為[3,4,1,5,2],第二個x為 4,序列變為[4,1,5,3,2],第三個x為 2,序列變為[2,4,1,5,3],現在要求輸出每個數字最左邊的位置和最右邊的位置,初始時每個數字在數字所表示的位置上,也就是1,2,3...n-1,n
題目分析:讀完題后很明顯的一個模擬的操作,但是需要合適的數據結構維護,不然復雜度承受不起,換個角度想,因為我們需要的是相對位置,所以當我們將應該操作的x提到隊首后,其他位置的數字就已經發生了相對位置的變化,當統計答案的時候,我們只需要通過區間查詢,查詢某個數之前有多少個數即可,這樣一想就一下子簡單了不少
既然需要區間查詢,那么線段樹和樹狀數組自然成為了不二之選,接下來我們需要實現上述操作,因為我們需要不斷將需要操作的數字進行前移,而樹狀數組是從1開始的,前移不太好實現,但是后移比較方便,所以我們不妨將數軸旋轉一下,讓原本的原點作為最大的地方,每一次將需要操作的數向后移動即達到了將操作數放到首位的操作,在整個的操作過程中就可以完成答案的更新,當一個數只要被操作的話,那么他的最小值肯定是1,至于最大值的話,統計答案時也可以利用樹狀數組前綴和的思想,答案顯然是query(N)-query(pos[x]-1)了,具體實現看代碼吧
注意因為m最大有3e5,所以樹狀數組記得開兩倍大小
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=6e5+100;int c[N+10],mmin[N],mmax[N],pos[N];int lowbit(int x) {return x&(-x); }int update(int pos,int val) {while(pos<=N){c[pos]+=val;pos+=lowbit(pos);} }int query(int pos) {int ans=0;while(pos){ans+=c[pos];pos-=lowbit(pos);}return ans; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){pos[i]=n-i+1;mmin[i]=mmax[i]=i;update(pos[i],1);}for(int i=n+1;i<=n+m;i++){int x;scanf("%d",&x);mmin[x]=1;mmax[x]=max(mmax[x],query(N)-query(pos[x]-1));update(pos[x],-1);pos[x]=i;update(pos[x],1); }for(int i=1;i<=n;i++)mmax[i]=max(mmax[i],query(N)-query(pos[i]-1));for(int i=1;i<=n;i++)printf("%d %d\n",mmin[i],mmax[i]);return 0; }?
總結
以上是生活随笔為你收集整理的CodeForces - 1288E Messenger Simulator(树状数组)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1288C T
- 下一篇: CodeForces - 375D Tr