zoukankan      html  css  js  c++  java
  • 2017-2018 ACM-ICPC Northern Eurasia(A.Archery Tournament)

    题目链接:https://vjudge.net/problem/Gym-101630A

    题意: n个事件,t=1 代表增加一个圆心为(x,y),半径为 abs(y)的靶子,t=2,代表射击的坐标为(x,y)并且询问是否在已出现的靶子上,如果在则输出第几个事件的编号,否则输出-1。

    该题有个坑点:(一开始没看到)一个靶子只能被射击一次。

    思路:可以用set存每个靶子的位置,但是需要对靶子按照前后空隙大小进行排序,这样之后我们就可以通过射击点的横坐标对set二分查找出最靠近其的靶子,然后就可以往后遍历是否存在一个靶子使得子弹在上面,但是光这样做在P5 就T了,仔细想了想发现,我们之前排序的作用,一旦我们的 x<x1-abs(y) 那么后面的靶子也不用再遍历了,直接退出循环,这样就会减少很多不必要的操作。

    然后还有简单的题解是通过线段树维护暴搜就好了:https://blog.csdn.net/lzc504603913/article/details/83958171

    代码:

    int n;
    struct node{
        ll x,y,id;
        bool operator<(const node a) const {
            return x+abs(y)<a.x-abs(a.y); //排序方法 
        }
    };
    bool dis(ll x1,ll y1,ll a,ll b)
    {
        return (x1-a)*(x1-a)+(y1-b)*(y1-b)<y1*y1;
    }
    set<node>s;
    void run()
    {
        scanf("%d",&n);
        ll t,a,b;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&t,&a,&b);
            if(t==1)
            {   
                node Node;
                Node.x=a;
                Node.y=b;
                Node.id=i;
                s.insert(Node);
            }
            else{
                node tmp;
                bool flag=0;
                tmp.x=a;
                tmp.y=0;
                set<node>::iterator it=s.lower_bound(tmp);
                while(it!=s.end())
                {   
                    ll x1=it->x,y1=it->y;
                    
                    if(dis(x1,y1,a,b))
                    {
                        flag=true;
                        printf("%lld
    ",it->id);
                        s.erase(it);
                        break;
                    }
                    if(it->x-a>abs(it->y)) break;//关键2; 
                    it++;
                }
                if(!flag) puts("-1");
            }
        }
    }
    signed main()
    {    
    //  int t=rd();
    //  while(t--) 
        run();
        return 0;
    }

    线段树的方法:

    #include<iostream>
    #include<deque>
    #include<memory.h>
    #include<stdio.h>
    #include<map>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<bitset>
    #include<set>
    #define INF (0x3f3f3f3f)
    using namespace std;
    typedef long long int ll;
    const int MAXN=200010;
     
    ll X[MAXN];
    ll Y[MAXN];
    int tot;
    vector<int> V[MAXN*30];
    int ls[MAXN*30];
    int rs[MAXN*30];
    int ans;
     
    bool check(ll x1,ll y1,ll x2,ll y2){
        if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<y1*y1)
            return 1;
        return 0;
    }
     
    void update(int L,int R,int C,int l,int r,int &rt){
     
        if(!rt)
            rt=++tot;
        if(L<=l&&r<=R)
        {
            V[rt].push_back(C);
            return;
        }
        int m=(l+r)>>1;
        if(L<=m)
            update(L,R,C,l,m,ls[rt]);
        if(R>m)
            update(L,R,C,m+1,r,rs[rt]);
    }
     
    void update(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            vector<int> tmp;
            for(auto &t:V[rt]){
                if(t!=ans){
                    tmp.push_back(t);
                }
            }
            V[rt]=tmp;
            return;
        }
        int m=(l+r)>>1;
        if(L<=m)
            update(L,R,l,m,ls[rt]);
        if(R>m)
            update(L,R,m+1,r,rs[rt]);
    }
     
    void query(int L,int R,int l,int r,int rt){
        if(!rt)
            return;
        for(auto &t:V[rt]){
            if(check(X[t],Y[t],L,R)){
                ans=t;
                return;
            }
        }
        if(l==r)
            return;
        int m=(l+r)>>1;
        if(L<=m)
            query(L,R,l,m,ls[rt]);
        else
            query(L,R,m+1,r,rs[rt]);
    }
     
     
    int main(){
     
        int N;
        scanf("%d",&N);
        int rt=0;
        for(int i=1;i<=N;i++){
     
            int op,x,y;
            scanf("%d%d%d",&op,&x,&y);
            if(op==1){
                X[i]=x;
                Y[i]=y;
                update(x-y,x+y,i,-INF,INF,rt);
            }
            else{
                ans=-1;
                query(x,y,-INF,INF,rt);
                printf("%d
    ",ans);
                if(ans!=-1)
                    update(X[ans]-Y[ans],X[ans]+Y[ans],-INF,INF,rt);
            }
        }
     
     
        return 0;
    }
     
     
     
     
     
  • 相关阅读:
    【NX二次开发】难点清单
    【NX二次开发】Block UI 目录
    Open C
    【NX二次开发】缝合片体例子UF_MODL_create_sew
    【NX二次开发】拉伸的偏置方向猜想与验证
    【NX二次开发】拉伸面、拉伸封闭曲线成片体UF_MODL_create_extrusion
    【NX二次开发】创建有界平面UF_MODL_create_bplane
    【VBA】一些判断
    【VBA】日期时间
    【VBA】单元格插入图片,单元格删除图片
  • 原文地址:https://www.cnblogs.com/zpj61/p/14335567.html
Copyright © 2011-2022 走看看