永不落幕的 zy [師大集訓 DAY 2] (圖文)

永不落幕的 zy


背景

人們的感情像洪水一樣襲來,頭暈目眩。


題目描述

zy 是一位擁有“共感”能力的少年,他總是能有意無意地感知別人的心情。
sm 是一位有着“心牆”的少女,她的感情無法傳遞出去。
就像命運一般,他們相遇了,彷彿 zy(的能力)就是爲了 sm 而存在一樣(事實上也確實如此) 。
sm 的心牆由許多迷茫組成,每個迷茫都希望從 X 軸上某一點去到另一點,而只有 zy 能消除 sm 的迷茫。
面對數量如此龐大的迷茫,zy 不曾想要放棄,但有些迷失了方向。
假設現在時間是 0 ,zy 在心牆的 1 位置,zy 每單位時間的移動速度是 1
若現在 zy 攜帶的迷茫想要去的地點和心牆上剩下的迷茫中在他右邊的個數大於等於左邊,則 zy 會向右移動,反之向左。
若現在 sm 沒有任何迷茫,則 zy 原地不動。
現在 zy 想知道,組成心牆的每個迷茫分別在什麼時候消失。
爲了儘快地讓 zy 能擁抱 sm,請你幫幫他。


輸入描述

第一行兩個數 NM 表示迷茫的數量和心牆的大小。
接下來 N 行,每行 3 個整數,tab ,表示這個迷茫出現在時刻 t ,希望從 ab


輸出描述

NN 個整數,表示每個迷茫分別在什麼時候消失


樣例輸入

2 10
1 2 5
7 4 5


樣例輸出

5
9


樣例解釋

時刻 1 ,有迷茫出現了!
時刻 2 ,zy 移動到了位置 2
時刻 5 ,zy 移動到了位置 5,迷茫消失。
時刻 7 ,有迷茫出現了!
時刻 8 ,zy 移動到了位置 4
時刻 9 ,zy 移動到了位置 5 ,迷茫消失。


數據範圍

對於 30% 的數據: N , M , t<=100
對於 60% 的數據: N , M , t<=10000
對於 100% 的數據:N , M , t<=100000


後記

我們的落幕,是新的開始。


附件

這裏寫圖片描述


Solution

首先想到的方法是按時間模擬……
然後發現大樣例中竟然有時間超過 int!!
於是便想會有實際操作(即有迷茫出現、加點或刪點)的時間點,必然是跳着走的。
所以便想用平衡樹來維護這個左右兩邊最近的可能發生事情的點。
結果打掛了,0 分……。
神犇Wza表示他只用了一個STL:set,並沒有打什麼平衡樹。
於是我也這麼打了。


Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#define LL long long
#define INF 922337203685775807LL
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))

using namespace std;

struct Obj{
    int a,b,t,num;
}obj[100010];

int n,m,now=1,z=1,Tot;
int want[100010],lft,rgt;
int here[100010],Time[100010];
LL end[100010];
bool go_before;
set<int>Splay;
set<int,greater<int> >Splay2;
vector<int>to[100010];
vector<int>frm[100010];

bool cmp(Obj x,Obj y){
    return x.t<y.t;
}

LL nxtT(LL x){
    return Time[lower_bound(Time+1,Time+n+1,x+1)-Time];
}

int main(){
#ifndef DEBUG
    freopen("sm.in","r",stdin);
    freopen("sm.out","w",stdout);
#endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&obj[i].t,&obj[i].a,&obj[i].b);
        obj[i].num=i;Time[i]=obj[i].t;
    }
    sort(obj+1,obj+n+1,cmp);
    sort(Time+1,Time+n+1);
    LL i=1;
    while(1){
        if(here[z]){
            if(go_before)rgt-=here[z];
            else lft-=here[z];
            for(vector<int>::iterator it=to[z].begin();it!=to[z].end();it++){
                want[obj[(*it)].b]++;
                frm[obj[(*it)].b].push_back((*it));
                if(obj[(*it)].b>z)rgt++;
                else lft++;
                Splay.insert(obj[(*it)].b);
                Splay2.insert(obj[(*it)].b);
            }
            Splay.erase(z);
            Splay2.erase(z);
            to[z].clear();
            here[z]=0;
        }
        if(want[z]){
            if(go_before)rgt-=want[z];
            else lft-=want[z];
            Tot-=want[z];
            for(vector<int>::iterator it=frm[z].begin();it!=frm[z].end();it++){
                end[obj[(*it)].num]=i;
            }
            Splay.erase(z);
            Splay2.erase(z);
            frm[z].clear();
            want[z]=0;
        }
        if(i==obj[now].t){
            while(obj[now].t==i){
                Tot++;
                if(obj[now].a==z){
                    if(obj[now].b>z)rgt++;
                    else lft++;
                    want[obj[now].b]++;
                    frm[obj[now].b].push_back(now);
                    Splay.insert(obj[now].b);
                    Splay2.insert(obj[now].b);
                    now++;
                    continue;
                }
                Splay.insert(obj[now].a);
                Splay2.insert(obj[now].a);
                to[obj[now].a].push_back(now);
                if(obj[now].a>z)rgt++;
                else lft++;
                here[obj[now].a]++;
                now++;
            }
        }
        if(!Tot){
            i=nxtT(i);
            if(now>n)break;
        }
        else if(rgt>=lft){
            go_before=true;
            LL tttt=i,nxtTT=nxtT(i);
            if(rgt)i=Min(i+((*Splay.upper_bound(z))-z),(nxtTT==0?INF:nxtTT));
            else i=nxtT(i);
            z=i-tttt+z;
        }
        else{
            go_before=false;
            LL tttt=i,nxtTT=nxtT(i);
            i=Min(i+(z-(*Splay2.upper_bound(z))),(nxtTT==0?INF:nxtTT));
            z=z-(i-tttt);
        }
    }
    for(int i=1;i<=n;i++)printf("%lld\n",end[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章