CodeForces 704A Thor
阿新 • • 發佈:2018-12-31
這個題是一個很好的題,首先理解題意就比較費勁,然後看上去是一個模擬的題,是需要用資料結構來維護的,暴力寫是超時的
分析題意:
題目中給定了三種操作
操作1:第x種應用增加一個未讀訊息
操作2:我把第x種應用的訊息全部讀完(標記為已讀)
操作3:我把所有的應用的訊息按照時間從先到後的順序,讀取x個
在讀取的時候,是可能會有重複讀取的。
n=1e5,q=1e5
然後,每個操作之後,我們需要輸出的是,在每個操作之後,當前的訊息庫中總共還有多少個未讀訊息
學到了一個線段樹來維護未讀訊息的姿勢!
竟然這樣寫沒有超時,我很詫異
首先,搞兩個陣列來標記,當前的第幾個應用的第幾個訊息是什麼(因為是vector的push_back(),所以會是按照時間順序的)
這個標記為vector<int> dui【maxn】
然後,我們還需要一個對全域性都進行記錄的vector<int> his
然後,很有意思的方法來了
對於操作1:我們使用線段樹來維護
就有update函式,讓x這個位置的值加1就好
然後his和dui【t】中都標記好當前的值就好
對於操作2:我們用另外一個update來搞
把這個x的位置上的值全部清0
然後,his中的所有值標為-1(表示讀過了)
然後dui【x】的值清空(已經全部讀過了)
對於操作3:如果當前需要判斷的值x不超過當期的最大插入數量,那麼直接輸出線段樹的根節點
否則,我們需要進行修改
強調一下容易理解錯的幾行程式碼
his.push_back(-1);
int Max=1;
這兩行程式碼,是為了防止直接查詢3的時候出錯用的(在裡面放了個無用資料)
下面貼程式碼:
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=3e5+500; int sum[maxn<<2]; vector<int> dui[maxn]; vector<int> his; void PushUp(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt){ if (l==r){ sum[rt]=0; return; } int m=(l+r)>>1; Build(lson); Build(rson); PushUp(rt); } void Update(int p,int x,int l,int r,int rt){ if (l==r){ sum[rt]=x; return; } int m=(l+r)>>1; if (p<=m) Update(p,x,lson); else Update(p,x,rson); PushUp(rt); } void Update1(int p,int x,int l,int r,int rt){ if (l==r){ sum[rt]+=x; return; } int m=(l+r)>>1; if (p<=m) Update1(p,x,lson); else Update1(p,x,rson); PushUp(rt); } int queryhe(int L,int R,int l,int r,int rt){ if (L<=l&&R>=r) return sum[rt]; int m=(l+r)>>1; int ret=0; if (L<=m) ret+=queryhe(L,R,lson); if (R>m) ret+=queryhe(L,R,rson); return ret; } int main(){ //freopen("input.txt","r",stdin); int n,q; while(scanf("%d%d",&n,&q)!=EOF){ memset(sum,0,sizeof(sum)); for(int i=0;i<maxn;i++) dui[i].clear(); his.clear(); his.push_back(-1); Build(1,n,1); int Max=1,total=0,op,t; for(int i=1;i<=q;i++){ scanf("%d%d",&op,&t); if (op==1){ total++; Update1(t,1,1,n,1); cout<<queryhe(1,n,1,n,1)<<endl; his.push_back(t); dui[t].push_back(total); } else if (op==2){ Update(t,0,1,n,1); cout<<queryhe(1,n,1,n,1)<<endl; int len=(int)dui[t].size(); for(int j=0;j<len;j++) his[dui[t][j]]=-1; dui[t].clear(); } else{ if (t<Max){ cout<<queryhe(1,n,1,n,1)<<endl; } else{ for(int j=Max;j<=t;j++){ int cur=his[j]; if (cur==-1) continue; Update1(cur,-1,1,n,1); his[j]=-1; } Max=t+1; cout<<queryhe(1,n,1,n,1)<<endl; } } } } return 0; }