• Rikka with Mista 线段树求交点个数


       由于上下线段是不可能有交点的

       可以先看左右线段树,按照y递增的顺序,对点进行排序。

       升序构造,那么对于从某一点往下的射线,对于L,R进行区间覆盖,线段交点个数就是单点的被覆盖的次数。

       降序构造,那么对于从某个点从下往上的射线,所有y坐标比期大的点都进行了区间覆盖,那么单点就是答案。

      最近脑子不太好。。。思路一定要清晰啊。。。

      

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<vector>
    #define pii pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define LL long long
    #define lson rt<<1
    #define rson rt<<1|1
    using namespace std;
    const int maxx = 2e5+6;
    struct node{
      int l,r,laze;
      int w;
    }tree[maxx<<2];
    vector<int>vx;
    vector<int>vy;
    struct Point{
      int x,y;
      char op;
    }p[maxx];
    int getx(int x){
      return lower_bound(vx.begin(),vx.end(),x)-vx.begin()+1;
    }
    int gety(int x){
      return lower_bound(vy.begin(),vy.end(),x)-vy.begin()+1;
    }
    void push_donw(int rt){
       if (tree[rt].laze){
          tree[lson].laze+=tree[rt].laze;
          tree[rson].laze+=tree[rt].laze;
          tree[lson].w+=tree[rt].laze*(tree[lson].r-tree[lson].l+1);
          tree[rson].w+=tree[rt].laze*(tree[rson].r-tree[rson].l+1);
          tree[rt].laze=0;
       }
    }
    void buildtree(int rt,int l,int r){
       tree[rt].l=l;
       tree[rt].r=r;
       tree[rt].laze=0;
       tree[rt].w=0;
       if (l==r){
         return ;
       }
       int mid=(l+r)>>1;
       buildtree(lson,l,mid);
       buildtree(rson,mid+1,r);
    }
    void update(int rt,int ql,int qr,int w){
       int l=tree[rt].l;
       int r=tree[rt].r;
       if (ql<=l && r<=qr){
          tree[rt].laze+=w;
          tree[rt].w+=w*(r-l+1);
          return;
       }
       int mid=(l+r)>>1;
       push_donw(rt);
       if (qr<=mid){
         update(lson,ql,qr,w);
       }else if(ql>mid){
         update(rson,ql,qr,w);
       }else {
         update(lson,ql,mid,w);
         update(rson,mid+1,qr,w);
       }
       tree[rt].w=tree[lson].w+tree[rson].w;
    }
    int query(int rt,int pos){
        int l=tree[rt].l;
        int r=tree[rt].r;
        if (l==r){
            return tree[rt].w;
        }
        int mid=(l+r)>>1;
        push_donw(rt);
        if (pos<=mid){
            return query(lson,pos);
        }else {
            return query(rson,pos);
        }
        tree[rt].w=tree[lson].w+tree[rson].w;
    }
    bool cmp(Point a,Point b){
       return a.y<b.y;
    }
    int main(){
      int t;
      int n,m,k;
      scanf("%d",&t);
      while(t--){
          scanf("%d%d%d",&n,&m,&k);
          vx.clear();
          vy.clear();
          for (int i=1;i<=k;i++){
              scanf("%d%d %c",&p[i].x,&p[i].y,&p[i].op);
              vx.push_back(p[i].x);
              vy.push_back(p[i].y);
          }
          sort(vx.begin(),vx.end());
          sort(vy.begin(),vy.end());
          vx.erase(unique(vx.begin(),vx.end()),vx.end());
          vy.erase(unique(vy.begin(),vy.end()),vy.end());
          sort(p+1,p+1+k,cmp);
          int sz=vx.size();
          buildtree(1,1,sz);
          LL ans=0;
          for (int i=1;i<=k;i++){
             if (p[i].op=='D'){
                ans+=query(1,getx(p[i].x));
             }else if (p[i].op=='L'){
                 update(1,1,getx(p[i].x),1);
             }else if (p[i].op=='R'){
                 update(1,getx(p[i].x),sz,1);
             }
          }
          buildtree(1,1,sz);
          for (int i=sz;i>=1;i--){
             if (p[i].op=='U'){
                 ans+=query(1,getx(p[i].x));
             }else if (p[i].op=='L'){
                 update(1,1,getx(p[i].x),1);
             }else if (p[i].op=='R'){
                 update(1,getx(p[i].x),sz,1);
             }
          }
          printf("%d
    ",ans+1);
      }
      return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    java传递String参数
    C++ string与int的互相转换
    java插入排序
    凸包Graham Scan算法实现
    求平面上N点最远两点和最近两点距离
    求最大公约数
    n个数连接得到最小或最大的多位整数(携程)
    Java快排
    背包问题
    二分查找离左边元素最近的(可以等于)
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11385369.html
Copyright © 2020-2023  润新知