zoukankan      html  css  js  c++  java
  • 崂山白花蛇草水 权值线段树套KDtree

    Description

    神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水。凭借着神犇Aleph的实
    力,他轻松地进了山东省省队,现在便是他履行诺言的时候了。蒟蒻Bob特地为他准备了999,999,999,999,999,999
    瓶崂山白花蛇草水,想要灌神犇Aleph。神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bo
    b最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答一些问题。具体说来,蒟蒻Bob会在一个宽敞
    的广场上放置一些崂山白花蛇草水(可视为二维平面上的一些整点),然后询问神犇Aleph在矩形区域(x1, y1), (
    x2, y2)(x1≤x2且y1≤y2,包括边界)中,崂山白花蛇草水瓶数第k多的是多少。为了避免麻烦,蒟蒻Bob不会在同
    一个位置放置两次或两次以上的崂山白花蛇草水,但蒟蒻Bob想为难一下神犇Aleph,希望他能在每次询问时立刻回
    答出答案。神犇Aleph不屑于做这种问题,所以把这个问题交给了你。

    Input

    输入的第一行为两个正整数N, Q,表示横纵坐标的范围和蒟蒻Bob的操作次数(包括放置次数和询问次数)。
    接下来Q行,每行代表蒟蒻Bob的一个操作,操作格式如下:
    首先第一个数字type,表示操作种类。type=1表示放置,type=2表示询问。
    若type=1,接下来会有三个正整数x, y, v,表示在坐标整点(x, y)放置v瓶崂山白花蛇草水。(1≤x, y≤N, 1≤v≤10^9)
    若type=2,接下来会有五个正整数x1, y1, x2, y2, k,表示询问矩形区域(x1, y1), (x2, y2)中,崂山白花蛇草水瓶数第k多的是多少。
    (1≤x1≤x2≤N,1≤y1≤y2≤N,1≤k≤Q)
    为了体现程序的在线性,你需要将每次读入的数据(除了type值)都异或lastans,其中lastans表示上次询问的答
    案。如果上次询问的答案为"NAIVE!ORZzyz."(见样例输出),则将lastans置为0。初始时的lastans为0。
    初始时平面上不存在崂山白花蛇草水。
    本题共有12组测试数据。对于所有的数据,N≤500,000。
    Q的范围见下表:
    测试点1-2     Q=1,000
    测试点3-7     Q=50,000
    测试点8-12     Q=100,000
     
     

    Output

    对于每个询问(type=2的操作),回答崂山白花蛇草水瓶数第k多的是多少。若不存在第k多的瓶数,
    请输出"NAIVE!ORZzyz."(输出不含双引号)。
     
    外层一个权值线段树来二分权值,线段树中每个节点开一颗 KDtree 来数点,这么边数点边二分即可.

    Code:

    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) //,freopen(s".out","w",stdout) 
    struct Data
    {
    	int ch[2],w,minv[2],maxv[2],p[2],siz,sum;  
    }node[20000000], arr[20000000]; 
    namespace KDtree
    {
    	#define maxn 20000000
    	#define Min(a,b) (a = a>b?b:a) 
    	#define Max(a,b) (a = b>a?b:a) 
    	int d,c_arr;    
    	std::queue<int>Q; 
    	void Init()
    	{
    		for(int i=1;i<maxn;++i) Q.push(i);                
    	} 
        int newnode(){ int q = Q.front(); Q.pop(); return q; }
    	bool cmp(Data i,Data j)
    	{      
    		return i.p[d]==j.p[d]?i.p[d^1]<j.p[d^1]:i.p[d]<j.p[d]; 
    	}
    	bool isout(int k,int x1,int y1,int x2,int y2)
    	{
    		if(node[k].maxv[0]<x1||node[k].minv[0]>x2||node[k].maxv[1]<y1||node[k].minv[1]>y2) return 1; 
    		return 0; 
    	}
    	bool isin(int k,int x1,int y1,int x2,int y2)
    	{
    		if(node[k].maxv[0]<=x2 && node[k].minv[0]>=x1&&node[k].maxv[1]<=y2&&node[k].minv[1]>=y1) return 1; 
    		return 0; 
    	}
    	void pushup(int x,Data p)
    	{
    		node[x].sum+=p.sum;
    		node[x].siz+=p.siz; 
    		Min(node[x].minv[0],p.minv[0]); 
    		Min(node[x].minv[1],p.minv[1]); 
    		Max(node[x].maxv[0],p.maxv[0]); 
    		Max(node[x].maxv[1],p.maxv[1]); 
    	}
    	int query(int x,int x1,int y1,int x2,int y2)
    	{
    		if(!x||isout(x,x1,y1,x2,y2)) return 0; 
    		if(isin(x,x1,y1,x2,y2))  
            {
                return node[x].sum; 
            }
    		int ans=0; 
    		if(node[x].p[0]>=x1&&node[x].p[0]<=x2&&node[x].p[1]>=y1&&node[x].p[1]<=y2) ans=1; 
    		ans += query(node[x].ch[0],x1,y1,x2,y2)+query(node[x].ch[1],x1,y1,x2,y2); 
    		return ans; 
    	} 
    	void dfs(int &o)
    	{
    		if(!o) return; 
    		dfs(node[o].ch[0]);
    		arr[++c_arr] = node[o];
    		arr[c_arr].sum=arr[c_arr].w=1; 
    		arr[c_arr].maxv[0]=arr[c_arr].minv[0]=arr[c_arr].p[0]; 
    		arr[c_arr].maxv[1]=arr[c_arr].minv[1]=arr[c_arr].p[1]; 
    		arr[c_arr].siz=1;      
    		Q.push(o);
    		dfs(node[o].ch[1]); 
    		o=0; 
    	}   
    	void rebuild(int &x,int l,int r,int o)
    	{
    		int mid=(l+r)>>1; 
    		d=o,std::nth_element(arr+l,arr+mid,arr+1+r,cmp); 
    		x=newnode(); 
    		node[x]=arr[mid]; 
    		node[x].minv[0]=node[x].maxv[0]=node[x].p[0]; 
    		node[x].minv[1]=node[x].maxv[1]=node[x].p[1]; 
    		node[x].sum=node[x].w=1;  
    		node[x].ch[0]=node[x].ch[1]=0;
    		node[x].siz=1; 
    		if(l<mid) rebuild(node[x].ch[0],l,mid-1,o^1), pushup(x, node[node[x].ch[0]]); 
    		if(r>mid) rebuild(node[x].ch[1],mid+1,r,o^1), pushup(x, node[node[x].ch[1]]); 
    	} 
    	void Reconstruct(int &u)
    	{
    		c_arr=0; 
    		dfs(u); 
    		rebuild(u,1,c_arr,d=0);       
    	} 
    	bool check(int son,int x)
    	{ 
    		if(son*10>x*9) return true; 
    		return false; 
    	}
    	void insert(int &x,Data a,int de,int tag)
    	{
    		if(!x)
    		{
    			x=newnode(); 
    			node[x].p[0]=node[x].maxv[0]=node[x].minv[0]=a.p[0]; 
    			node[x].p[1]=node[x].maxv[1]=node[x].minv[1]=a.p[1]; 
    			node[x].sum=node[x].w=1;
    			node[x].siz=1,node[x].ch[0]=node[x].ch[1]=0; 
    			return; 
    		}
    		d = de;
    		int is=0;          
    		if(cmp(a,node[x]) == 1)          
    		{                    
    			is = check(node[node[x].ch[0]].siz+1,node[x].siz+1);
    			insert(node[x].ch[0],a,de^1,is||tag);
    			pushup(x,a); 
    		}
    		//a is bigger (rson) 
    		else 
    		{
    			is = check(node[node[x].ch[1]].siz+1,node[x].siz+1);
    			insert(node[x].ch[1],a,de^1,is||tag);
    			pushup(x,a); 
    		}      
    	if(tag && is) Reconstruct(x);   
    	}
    };       
    #define y1 opopopop 
    int lson[2000000],rson[2000000],rt[2000000]; 
    int x1,y1,x2,y2, tot=0,root=0;  
    void modify(int &x,int l,int r,int k,Data i)
    {   
    	if(!x) x = ++tot;           
    	KDtree::insert(rt[x],i,0,0);                  
    	if(l==r) return;         
    	int mid = (l+r)>>1; 
    	if(k <= mid) modify(lson[x],l,mid,k,i); 
    	else modify(rson[x],mid+1,r,k,i); 
    }        
    int query(int x,int l,int r,int kth)
    {              
    	if(l==r) return l; 
    	int u = KDtree::query(rt[rson[x]],x1,y1,x2,y2);                     
    	int mid = (l + r) >> 1;             
    	if(u < kth) 
    	    return query(lson[x],l,mid,kth-u);  
    	else 
    	    return query(rson[x],mid+1,r,kth);  
    }
    int Query(int kth)
    {    
    	return query(root,0,1000000000,kth);      
    }
    int n,q,lastans=0; 
    int main()
    {
     	// setIO("input"); 
    	KDtree::Init();  
    	scanf("%d%d",&n,&q);            
    	for(int cc=1;cc<=q;++cc)   
    	{
    		int opt,a,b,c,d; 
    		scanf("%d",&opt); 
    		if(opt==1)
    		{    
    			scanf("%d%d%d",&a,&b,&c);     
                a^=lastans,b^=lastans,c^=lastans; 
    			Data f; 
    			f.p[0]=f.maxv[0]=f.minv[0]=a;
    			f.p[1]=f.maxv[1]=f.minv[1]=b; 
    			f.ch[0]=f.ch[1]=0; 
    			f.siz=1;    
    			f.sum=f.w=1;                 
    			modify(root,0,1000000000,c,f);   
    		}
    		if(opt==2)
    		{
    			scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&a); 
    		    x1^=lastans,y1^=lastans,x2^=lastans,y2^=lastans,a^=lastans;             
    			lastans = Query(a); 
    			if(lastans==0)   
    			    printf("NAIVE!ORZzyz.
    ");   
    			else  
    			    printf("%d
    ",lastans); 
    		}
    	}
    	return 0; 
    }     
    

      

  • 相关阅读:
    VUE单页模板
    Nacos(作为配置中心)
    OpenFeign与Nacos(作为注册中心) 远程调用
    Nacos 服务注册
    Docker 安装Redis
    Docker安装Mysql
    多线程之CAS和ABA
    Volatile
    JAVA语言的特点
    判断多选按钮被选中两种方法
  • 原文地址:https://www.cnblogs.com/guangheli/p/10959473.html
Copyright © 2011-2022 走看看