zoukankan      html  css  js  c++  java
  • CF369E Valera and Queries kdtree

    给你一堆线段,求:一个区间内包含的本质不同线段种类数(只要线段有一部分在区间中就算是包含)

    考虑容斥:总线段数-被那些没有询问的区间完全覆盖的数量.

    用离线+树状数组数点或者 KDtree 数点即可.

    #include <bits/stdc++.h>  
    #define N 300005 
    using namespace std;  
    void setIO(string s) 
    {
        string in=s+".in";       
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout); 
    }
    namespace kd
    {   
        int d; 
        struct node 
        { 
            int ch[2],p[2],minv[2],maxv[2],sum,w;      
        }t[N];            
        bool cmp(node a,node b) 
        {      
            return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];   
        }
        int isin(int p,int x1,int y1,int x2,int y2) 
        { 
            return t[p].minv[0]>=x1&&t[p].maxv[0]<=x2&&t[p].minv[1]>=y1&&t[p].maxv[1]<=y2;
        }
        int isout(int p,int x1,int y1,int x2,int y2) 
        {
            return t[p].maxv[0]<x1||t[p].minv[0]>x2||t[p].maxv[1]<y1||t[p].minv[1]>y2;    
        }
        void pushup(int x,int y) 
        {          
            t[x].sum+=t[y].sum;    
            for(int i=0;i<2;++i) 
            {
                t[x].minv[i]=min(t[x].minv[i],t[y].minv[i]);   
                t[x].maxv[i]=max(t[x].maxv[i],t[y].maxv[i]);    
            }
        }
        int build(int l,int r,int o) 
        {
            d=o;  
            int mid=(l+r)>>1;  
            nth_element(t+l,t+mid,t+1+r,cmp);         
            for(int i=0;i<2;++i) t[mid].minv[i]=t[mid].maxv[i]=t[mid].p[i];    
            t[mid].sum=1;   
            t[mid].ch[0]=t[mid].ch[1]=0;                                      
            if(mid>l) t[mid].ch[0]=build(l,mid-1,o^1),pushup(mid,t[mid].ch[0]);  
            if(r>mid) t[mid].ch[1]=build(mid+1,r,o^1),pushup(mid,t[mid].ch[1]);   
            return mid;         
        }
        int query(int p,int x1,int y1,int x2,int y2) 
        {
            if(isin(p,x1,y1,x2,y2)) return t[p].sum;   
            if(isout(p,x1,y1,x2,y2)) return 0;   
            int re=(t[p].p[0]>=x1&&t[p].p[0]<=x2&&t[p].p[1]>=y1&&t[p].p[1]<=y2);     
            if(t[p].ch[0]) re+=query(t[p].ch[0],x1,y1,x2,y2);  
            if(t[p].ch[1]) re+=query(t[p].ch[1],x1,y1,x2,y2); 
            return re;   
        }
    };     
    namespace IO
    {
        char *p1,*p2,buf[100000];
        #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
        int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    };
    int arr[N];   
    int main() 
    {
        // setIO("input");                  
        int n,m,i,j,root; 
        n=IO::rd(),m=IO::rd();   
        for(i=1;i<=n;++i)          
            kd::t[i].p[0]=IO::rd(),kd::t[i].p[1]=IO::rd();                                            
            // scanf("%d%d",&kd::t[i].p[0],&kd::t[i].p[1]); 
        root=kd::build(1,n,0);       
        for(i=1;i<=m;++i) 
        { 
            int k=IO::rd(),re=0;   
            // scanf("%d",&k);      
            for(j=1;j<=k;++j) arr[j]=IO::rd(); 
            arr[0]=0,arr[k+1]=1000002;   
            for(j=0;j<=k;++j) 
            {
                if(arr[j+1]>arr[j]+1) 
                {
                    re+=kd::query(root,arr[j]+1,arr[j]+1,arr[j+1]-1,arr[j+1]-1);   
                }
            }    
            printf("%d
    ",n-re);   
        }
        return 0; 
    }
    

      

  • 相关阅读:
    Android比较实用的属性
    软件版本命名规则
    Dhroid框架笔记(DhNet、Adapter)
    Activity对话框
    Dhroid框架笔记(IOC、EventBus)
    Eclipse快捷键
    解析Excel_Jxl
    面试题
    java基础——值传递和应用传递
    java基础——子类继承父类程序执行顺序
  • 原文地址:https://www.cnblogs.com/guangheli/p/11759244.html
Copyright © 2011-2022 走看看