牛客暑假多校第六场I-Team Rocket

一、题意

我们是穿越银河的火箭队.......

给出若干个区间,之后给出若干个点,要求对每个点求出,第一个覆盖点的区间的数量,之后用当前所有点覆盖的区间的序号的乘积结合输入的Y来生成下一位点。最后输出,每个区间第一次覆盖的点的序号。

There are n trains running between Kanto and Johto region. Assuming the railway is a number line, the i-th train travels from coordinate li to coordinate ri (both inclusive).
One day, m Team Rocket members invaded the railway system successfully. The i-th Team Rocket member was going to destroy the transportation hub with coordinate xi. Once a transportation hub within the driving range of a train is destroyed, the train's itinerary will be canceled immediately.
Giovanni wants to know how many train trips will be firstly canceled after each attack.
After all the attacks finished, for each train Giovanni needs to know that in which attack its itinerary was firstly canceled, or it was unaffected at all.

二、题解

考虑区间可以被理解成二维的点对,则建立一个线段树,每个树节点挂一个vector,用来保存"所有起点在当前节点的点对"。之后要求每个节点的点按照,按照结尾大小有序排列。最后我们每次查一个点,实质上是在查所有起点小于当前给定节点,同时终点大于当前给定节点的所有点对。则,再使用一个数组或者别的什么东西记录下点的首次查询的点的编号。

#include<bits/stdc++.h>
using namespace std;
 
#define ll long long 
#define pp pair<ll,ll>
#define veci vector<int>
#define idx(x) (lower_bound(mapp,mapp+mapp_num,x)-mapp)
 
const int MAXN = 300233;
const ll MOD = 998244353;
 
class Node{
    public:
        int l,r,lc,rc;
        veci points;
};
Node nodes[MAXN*2];
 
ll mapp[MAXN];
int mapp_num;
 
int nodes_num;
 
pp orders[MAXN];
int seq[MAXN];
int first_erased[MAXN];
 
int t,n,m;
int cases;
 
int cntt;
 
bool cmp(int a,int b)
{
    return orders[a].second<orders[b].second;
}
 
void tree_init(int a,int b)
{
    int now = nodes_num++;
    nodes[now].l = a;
    nodes[now].r = b;
    nodes[now].points.clear();
    if(a == b-1)return ;
    int mid = (a+b)/2;
    nodes[now].lc = nodes_num;
    tree_init(a,mid);
    nodes[now].rc  =nodes_num;
    tree_init(mid,b);
}
 
void tree_insert(int now,int pos,int key){
    int l = nodes[now].l;
    int r = nodes[now].r;
    if(l == r-1){
        nodes[now].points.push_back(key);
        // cout<<"check_tree: "<<now<<" "<<nodes[now].points.size()<<endl;
        return ;
    }
    int mid = (l+r)/2;
    if(pos < mid)tree_insert(nodes[now].lc,pos,key);
    else tree_insert(nodes[now].rc,pos,key);
}
 
void tree_merge(int now)
{
    int l = nodes[now].l;
    int r = nodes[now].r;
    if(l == r-1)return ;
 
    tree_merge(nodes[now].lc);
    tree_merge(nodes[now].rc);
    int lc = nodes[now].lc;
    int rc = nodes[now].rc;
    int pl,pr;
    pl = pr = 0;
    int lenl = nodes[lc].points.size();
    int lenr = nodes[rc].points.size();
    while(pl!= lenl || pr != lenr){
        if(pl!= lenl && pr != lenr){
            if( cmp(nodes[lc].points[pl],nodes[rc].points[pr]) )nodes[now].points.push_back(nodes[lc].points[pl++]);
            else nodes[now].points.push_back(nodes[rc].points[pr++]);
        }else{
            while(pl!=lenl)nodes[now].points.push_back(nodes[lc].points[pl++]);
            while(pr!=lenr)nodes[now].points.push_back(nodes[rc].points[pr++]);
        }
    }
    // cout<<"check_merge: "<<nodes[now].points.size()<<endl;
 
}
 
ll tree_erase(int now,int a,int b,int num,ll key){
    int l = nodes[now].l;
    int r = nodes[now].r;
    ll ret = 0;
    if(l == a&&r == b){
        int len = nodes[now].points.size();
        for(int i=len-1;i>=0;i--){
            int tar = nodes[now].points[i];
            if(orders[tar].second < key)break;
            nodes[now].points.pop_back();
            if(!first_erased[tar]){
                cntt++;
                first_erased[tar] = num;
                if(!ret)ret =1 ;
                ret *= tar;
                ret %= MOD;
            }
        }return ret;
    }
    int mid = (l+r)/2;
    if(a < mid){
        ll tmp = tree_erase(nodes[now].lc,a,min(b,mid),num,key);
        if(tmp)ret = tmp;
        tmp = 0 ;
        if(b>mid)tmp = tree_erase(nodes[now].rc,mid,b,num,key);
        if(tmp && ret)ret *= tmp;
        if(!ret && tmp)ret = tmp;
    }else ret = tree_erase(nodes[now].rc,a,b,num,key);
    return ret%MOD;
}
 
void init()
{
    cin>>n>>m;
    nodes_num = 0;
    mapp_num = 0;
    memset(first_erased,0,sizeof(int)*(n+23));
    mapp[mapp_num++] = LLONG_MIN;
    mapp[mapp_num++] = LLONG_MAX;
    for(int i=1;i<=n;++i){
        cin>>orders[i].first>>orders[i].second;
        mapp[mapp_num++] = orders[i].first;
        seq[i] = i;
    }
    tree_init(0,mapp_num);
    sort(mapp,mapp+mapp_num);
    sort(seq+1,seq+1+n,cmp);
 
    for(int i=1;i<=n;++i)
    {
        // cout<<"check_seq: "<<idx(orders[seq[i]].first)<<endl;
        tree_insert(0,idx(orders[seq[i]].first),seq[i]);
    }
    tree_merge(0);
    ll last = 0;
    printf("Case #%d:\n",cases-t);
    for(int i=1;i<=m;++i){
        ll y;
        cin>>y;
        y ^= last;
        cntt = 0;
        int index = idx(y);
        if(mapp[index] == y)index++;
        // cout<<"check_y "<<y<<"index: "<<index<<endl;
        last = tree_erase(0,0,index,i,y);
        printf("%d\n",cntt);
    }
    for(int i=1;i<=n;++i){
        printf("%d",first_erased[i]);
        if(i == n)printf("\n");
        else printf(" ");
    }
}
 
int main()
{
    cin.sync_with_stdio(false);
    cin>>t;cases = t;
    while(t--)init();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/rikka/p/9458002.html
今日推荐