[NOI2019]弹跳

黑科技!线段树套set,空间一个log,代码巨短,就是。。。常数有点大。

把每个矩形当做一个点用到了再建边用过了就删除什么的套路就不说了

#include<bits/stdc++.h>
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout);
#define N 151000
#define inf 123456789123456789
#define db double
#define P 1000000007
#define mid (l+r>>1)
#define d(x) (x>>cur-1&1)
#define it set<city>::iterator 
using namespace std;
int n,m,w,h,dis[N],vis[N],tp[N],top;
struct city{
    int x,y,id;
    friend bool operator <(city x,city y){ return x.y==y.y?x.x<y.x:x.y<y.y;}
}a[N];
set<city>s[N*2];
struct edge{
    int p,t,l,r,d,u;
}b[N];
struct node{
    int p,t;
    friend bool operator <(node x,node y){ return x.t>y.t;}
};
priority_queue<node> q;
vector<int> v[N];
void ins(int k,int l,int r,int v){
    s[k].insert(a[v]);
    if(l==r) return;
    if(a[v].x<=mid) ins(k*2,l,mid,v);
    else ins(k*2+1,mid+1,r,v);
}
void del(int k,int l,int r,int v){
    s[k].erase(a[v]);
    if(l==r) return;
    if(a[v].x<=mid) del(k*2,l,mid,v);
    else del(k*2+1,mid+1,r,v);
}
void work(int k,int l,int r,int x,int t){
    if(b[x].l<=l&&r<=b[x].r){
        for(it i=lower_bound(s[k].begin(),s[k].end(),(city){0,b[x].d,0});i!=s[k].end()&&(*i).y<=b[x].u;i++){
            dis[(*i).id]=t;tp[++top]=(*i).id;
            for(auto j:v[(*i).id])q.push({j,t+b[j].t});
        }
        while(top) del(1,1,n,tp[top--]);
        return;
    }
    if(b[x].l<=mid) work(k*2,l,mid,x,t);
    if(b[x].r>mid) work(k*2+1,mid+1,r,x,t);
}
signed main(){
    scanf("%d%d%d%d",&n,&m,&w,&h);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,ins(1,1,n,i);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d%d%d",&b[i].p,&b[i].t,&b[i].l,&b[i].r,&b[i].d,&b[i].u);
        v[b[i].p].push_back(i);
    }
    for(auto i:v[1]) q.push({i,b[i].t});
    while(!q.empty()){
        node t=q.top();q.pop();
        if(vis[t.p]) continue;vis[t.p]=1;
        work(1,1,n,t.p,t.t);
    }
    for(int i=2;i<=n;i++) printf("%d
",dis[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/blogoflyn/p/13252037.html