zoukankan      html  css  js  c++  java
  • BZOJ 4369: [IOI2015]teams分组

    把一个人看成二维平面上的一个点,把一个K[i]看成左上角为(0,+max),右下角为(K[i],K[i])的一个矩阵,那么可以很好地描述人对于询问是否合法(我也不知道他怎么想到这东西的)

    然后把一组询问排序,按照K[i]从小到大依次处理,定义一个取点的方式为尽量取纵坐标小的点,那么可以构造出一种方案使得对于每一块区域不能取的点的最大纵坐标递减

    (我也不知道他怎么想到这东西的)

    单调栈维护每一块被取过的点的最大纵坐标,那么随着K[i]的增大,区域会被合并

    二维平面数点,主席树

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int N,n,cnt,tree[10000005],sz[200005],h[200005],stack[200005],K[200005],root[500005],ls[10000005],rs[10000005];
    struct node{
    	int x,y;
    }e[1000005];
    bool cmp(node a,node b){
    	return a.x<b.x;
    }
    void insert(int pre,int &now,int l,int r,int ID){
    	now=++cnt;
    	tree[now]=tree[pre]+1;
    	ls[now]=ls[pre];
    	rs[now]=rs[pre];
    	if (l==r) return;
    	int mid=(l+r)>>1;
    	if (ID<=mid) insert(ls[pre],ls[now],l,mid,ID);
    	else insert(rs[pre],rs[now],mid+1,r,ID);
    }
    int query_K(int pre,int now,int l,int r,int K){
    	if (l==r) return l;
    	int mid=(l+r)>>1;
    	int ANS=tree[rs[now]]-tree[rs[pre]];
    	if (ANS>=K) return query_K(rs[pre],rs[now],mid+1,r,K);
    	else return query_K(ls[pre],ls[now],l,mid,K-ANS);
    }
    int query(int pre,int now,int l,int r,int K){
    	if (!now) return 0;
    	if (l==r) return tree[now]-tree[pre];
    	int mid=(l+r)>>1;
    	if (K<=mid) return tree[rs[now]]-tree[rs[pre]]+query(ls[pre],ls[now],l,mid,K);
    	else return query(rs[pre],rs[now],mid+1,r,K);
    }
    int main(){
    	scanf("%d",&n);
    	for (int i=1; i<=n; i++) scanf("%d%d",&e[i].x,&e[i].y);
    	sort(e+1,e+n+1,cmp);
    	N=n+1;
    	int head=1;
    	for (int i=1; i<=N; i++){
    		root[i]=root[i-1];
    		while (head<=n && e[head].x==i) insert(root[i],root[i],1,N,e[head++].y);
    	}
    	int q;
    	scanf("%d",&q);
    	while (q--){
    		int m;
    		scanf("%d",&m);
    		for (int i=1; i<=m; i++) scanf("%d",&K[i]);
    		sort(K+1,K+m+1);
    		int top=0;
    		for (int i=1; i<=m; i++){
    			while (top && h[top]<K[i]) top--;
    			int Sz=sz[top];
    			Sz+=query(root[K[stack[top]]],root[K[i]],1,N,K[i])-K[i];
    			if (Sz<0){
    				printf("0
    ");
    				break;
    			}
    			else if (i==m){
    				printf("1
    ");
    				break;
    			}
    			int H=query_K(root[K[stack[top]]],root[K[i]],1,N,Sz-sz[top]);
    			while (H>h[top] && top){
    				top--;
    				H=query_K(root[K[stack[top]]],root[K[i]],1,N,Sz-sz[top]);
    			}
    			stack[++top]=i;
    			sz[top]=Sz;
    			h[top]=H;
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    解决调用未定义 swoole_async_readfile函数问题
    7000字 Redis 超详细总结笔记总 | 收藏必备!
    C/C++语言编程修养
    glib 队列
    sprintf 详解
    json 需替换 特殊字符串
    glib 关系
    glib 简介
    gprof 代码效率测量
    glib 树
  • 原文地址:https://www.cnblogs.com/silenty/p/9852419.html
Copyright © 2011-2022 走看看