1. 程式人生 > >CodeForces 704A Thor

CodeForces 704A Thor

這個題是一個很好的題,首先理解題意就比較費勁,然後看上去是一個模擬的題,是需要用資料結構來維護的,暴力寫是超時的

分析題意:

題目中給定了三種操作

操作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;
}