永不落幕的 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章