zoukankan      html  css  js  c++  java
  • BZOJ4548 小奇的糖果

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

     

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

     

    Description

    有 N 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾

    起多少糖果,使得获得的糖果并不包含所有的颜色。

    Input

    包含多组测试数据,第一行输入一个正整数 T 表示测试数据组数。

    接下来 T 组测试数据,对于每组测试数据,第一行输入两个正整数 N、K,分别表示点数和颜色数。
    接下来 N 行,每行描述一个点,前两个数 x, y (|x|, |y| ≤ 2^30 - 1) 描述点的位置,最后一个数 z (1 ≤ z ≤
     k) 描述点的颜色。
    对于 100% 的数据,N ≤ 100000,K ≤ 100000,T ≤ 3

    Output

    对于每组数据在一行内输出一个非负整数 ans,表示答案

     

     

    Sample Input

    1
    10 3
    1 2 3
    2 1 1
    2 4 2
    3 5 3
    4 4 2
    5 1 2
    6 3 1
    6 7 1
    7 2 3
    9 4 2

    Sample Output

    5
     
     
    正解:树状数组+双向链表
    解题报告:
         注意题目中说的是线段而不是直线,若是直线的话线性扫一遍即可。
      那么对于这道题,如果单独考虑一种颜色,那么讲这种颜色的所有点按x排序之后,假设相邻两个点的横坐标分别为p,q,则[p+1,q-1]中一定再没有这种颜色的糖果,这个证明的话可以显然。
      由于题目要求不包含所有的糖果的情况下可以取到的最大糖果数量,显然[p+1,q-1]区间内的点一定满足题意。
      依据上述结论,不难得出具体做法:按y轴从小到大排序,从下往上处理,先默认我们只取线段以上的部分(以下的部分可以把纵坐标反号再做一次),可以想象成是一根直线往上推进,每当我扫描到一个点,就可以考虑用与这个点颜色相同的左右两个点之间的部分更新答案,正确性上面已经证明了。同时消除这个点的影响。
      不妨用树状数组维护区间数量,双向链表维护颜色相同的左右两个点,这样的话可以在nlogn的时间里完成操作。
     
     
    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    using namespace std;
    typedef long long LL;
    const int MAXN = 100011;
    int n,C[MAXN],L,k,yan[MAXN],ans,X[MAXN];
    int last[MAXN],next[MAXN],c[MAXN];
    struct node{int x,y,col,pos;}a[MAXN];
    inline bool cmpx(node q,node qq){ if(q.x==qq.x) return q.y>qq.y; return q.x<qq.x; }
    inline bool cmpy(node q,node qq){ return q.y<qq.y; }
    inline void add(int x,int val){ while(x<=L) c[x]+=val,x+=x&(-x); } 
    inline int query(int x){ if(x==0) return 0; int tot=0; while(x>0) tot+=c[x],x-=x&(-x); return tot; }
    inline void update(int l,int r){ if(l>r) return ; int tot=query(r)-query(l-1); if(tot>ans) ans=tot; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void solve(){
    	X[0]=0; X[n+1]=L; memset(last,0,sizeof(last)); memset(next,0,sizeof(next)); memset(yan,0,sizeof(yan));
    	for(int i=1;i<=n;i++) add(a[i].x,1); sort(a+1,a+n+1,cmpx);
    	for(int i=1;i<=n;i++) {
    		last[a[i].pos]=yan[a[i].col]; next[a[i].pos]=n+1;
    		if(yan[a[i].col]) next[yan[a[i].col]]=a[i].pos;
    		update(X[yan[a[i].col]]+1,X[a[i].pos]-1);
    		yan[a[i].col]=a[i].pos;
    	}
    	for(int i=1;i<=k;i++) update(X[yan[i]]+1/*!!!*/,L);
    	sort(a+1,a+n+1,cmpy);
    	for(int i=1,head=1;i<=n;i=head) {
    		while(head<=n && a[head].y==a[i].y) {
    			add(a[head].x,-1);
    			head++;
    		}	  		
    		for(int j=i;j<head;j++) {
    			update(X[last[a[j].pos]]+1,X[next[a[j].pos]]-1); 
    			next[last[a[j].pos]]=next[a[j].pos]; 
    			last[next[a[j].pos]]=last[a[j].pos];
    		}	 
    	}
    }
    
    inline void work(){
    	int T=getint(); 
    	while(T--) {
    		n=getint(); k=getint(); ans=0; L=0; for(int i=1;i<=n;i++) a[i].x=getint(),a[i].y=getint(),a[i].col=getint(),C[i]=a[i].x,a[i].pos=i;
    		sort(C+1,C+n+1); L=unique(C+1,C+n+1)-C-1; for(int i=1;i<=n;i++) a[i].x=lower_bound(C+1,C+L+1,a[i].x)-C,X[i]=a[i].x; L++;
    		solve(); for(int i=1;i<=n;i++) a[i].y=-a[i].y;	solve();
    		printf("%d
    ",ans);
    	}
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

      

     
  • 相关阅读:
    jquery 序列化form表单
    nginx for windows 安装
    nodejs idea 创建项目 (一)
    spring 配置 shiro rememberMe
    idea 2018 解决 双击shift 弹出 search everywhere 搜索框的方法
    redis 在windows 集群
    spring IOC控制反转和DI依赖注入
    redis 的安装
    shiro 通过jdbc连接数据库
    handlebars的用法
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6201857.html
Copyright © 2011-2022 走看看