首页 > 其他 > 详细

Gym 101630A(线段树)

时间:2021-02-02 22:11:23      阅读:30      评论:0      收藏:0      [点我收藏+]

观察到一点,因为每个圆都与x轴相切,因此一条垂直线上,最多只有log(值域)个圆

因此我们离散化之后,用线段树维护每个x先上的点,之后对于每个询问,暴力判断它上面的log个圆圈观察是否有符合答案的式子

但是我写的方法好像很丑,看上去复杂度好像没啥问题但是会T,懒得改了就先放上来记录一下思路

技术分享图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int N=1e6+10;
const ll mod=998244353;
struct node{
    int l,r;
    set<int> s;
}tr[N<<3];
struct seg{
    int t;
    ll x,y;
}in[N];
pll ans[N];
pll res[N];
int dx[N];
int n;
vector<int> num;
set<int> tmp;
int find(int x){
    return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void modify(int u,int l,int r,int x,int sign){
    if(tr[u].l>r||tr[u].r<l)
        return ;
    if(tr[u].l>=l&&tr[u].r<=r){
        if(sign){
            tr[u].s.insert(x);
        }
        else{
            tr[u].s.erase(x);
        }
    }
    if(tr[u].l==tr[u].r)
        return;
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,x,sign);
    if(r>mid)
        modify(u<<1|1,l,r,x,sign);
}
void query(int u,int l){
    if(tr[u].l==tr[u].r){
        for(auto x:tr[u].s){
            tmp.insert(x);
        }
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        query(u<<1,l);
    else
        query(u<<1|1,l);
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        int t,x,y;
        cin>>t>>x>>y;
        in[i]={t,x,y};
        num.push_back(x);
        if(t==1){
            num.push_back(x-y);
            num.push_back(x+y);
        }
        if(t==1){
            ans[i].first=x,ans[i].second=y;
        }
    }
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    for(i=1;i<=n;i++){
        if(in[i].t==1){
            int posx=find(in[i].x-in[i].y);
            int posy=find(in[i].x+in[i].y);
            res[i]={posx,posy};
        }
        else{
            dx[i]=find(in[i].x);
        }
    }
    build(1,1,(int)num.size()+100);
    for(i=1;i<=n;i++){
        if(in[i].t==1){
            int posx=res[i].first;
            int posy=res[i].second;
            modify(1,posx,posy,i,1);
        }
        else{
            tmp.clear();
            int pos=dx[i];
            query(1,pos);
            int flag=0;
            for(auto x:tmp){
                ll da=(ans[x].first-in[i].x)*(ans[x].first-in[i].x);
                ll db=(ans[x].second-in[i].y)*(ans[x].second-in[i].y);
                if(da+db<ans[x].second*ans[x].second){
                    int posx=res[x].first;
                    int posy=res[x].second;
                    modify(1,posx,posy,x,0);
                    cout<<x<<endl;
                    flag=1;
                    break;
                }
            }
            if(!flag){
                cout<<-1<<endl;
            }
        }
    }
    return 0;
}
View Code

 

Gym 101630A(线段树)

原文:https://www.cnblogs.com/ctyakwf/p/14363832.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!