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

    →原题传送门←(by Hzwer)

    「题目背景」

    小奇不小心让糖果散落到了地上,它对着满地的彩色糖果胡思乱想。

    「问题描述」

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

    「输入格式」

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

    接下来 T 组测试数据,对于每组测试数据,第一行输入两个正整数 N、K,分别表示点数和颜色数。

    接下来 N 行,每行描述一个点,前两个数 x, y (|x|, |y| ≤ 2^30 – 1) 描述点的位置,最后一个数 z (1 ≤ z ≤ k) 描述点的颜色。

    「输出格式」

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

    「样例输入」

    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

    「样例输出」

    5

    「数据范围」

    对于 30% 的数据,N ≤ 100;

    对于 60% 的数据,N ≤ 5000;

    对于 100% 的数据,N ≤ 100000,K ≤ 100000,T ≤ 3。


     

     

     

    第N道小奇系列的题目了(之前好像也做过一道小奇的糖果来着,不过那是IOI改编,有点难

    模拟考的时候写了暴力居然没有分(!)

     

    下面是自己写的题解:

    • 这是在糖果是撒在二维平面里的,所以我们可以通过其中一维的坐标离散化,然后通过枚举,转成单一一维里的问题。
    • 把横坐标离散化掉,按横坐标从左到右,把横坐标相邻的糖果用双向的链表串在一起(对于有不同颜色的序列,这样的操作很常见哦,记下来记下来)。
    • 所以每一次在两个相同颜色的糖果之间数一下其它糖果的数量,就可以来更新ans了,可以用树状数组来维护区间里的糖果数量。
    • 然后想象一条扫描线,从下到上扫一遍,每一次把扫描线上的点屏蔽掉,再更新一次答案,这样就可以完成对于水平线上糖果的更新了。
    • 那水平线下的怎么更新呢?一样的嘛,为了减少编程复杂度,我们把纵坐标取相反数,用一样的办法再做一次就可以了。

    代码~

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 
      7 #define For(i,a,b) for(register int i=a;i<=b;++i)
      8 #define Re register
      9 #define Pn putchar('
    ')
     10 using namespace std;
     11 const int N=1e5+10;
     12 int Lc[N],Rc[N],lst[N];
     13 int X[N],sX[N];
     14 struct Point{
     15     int x,y,cl,id;
     16 }pt[N];
     17 int c[N],n,m,x,y,Kx,ans=0;
     18 
     19 inline void read(int &v){
     20     v=0; bool fg=0;
     21     char c=getchar(); if(c=='-')fg=1;
     22     while(c<'0'||c>'9'){c=getchar(); if(c=='-')fg=1;}
     23     while(c>='0'&&c<='9'){v=v*10+c-'0',c=getchar(); if(c=='-')fg=1;}
     24     if(fg)v=-v;
     25 }
     26 void write(int x){
     27     if(x>9)write(x/10);
     28     int xx=x%10;
     29     putchar(xx+'0');
     30 }
     31 bool cmpX(const Point &a,const Point &b){
     32     return a.x<b.x;
     33 }
     34 bool cmpY(const Point &a,const Point &b){
     35     return a.y<b.y;
     36 }
     37 
     38 
     39 int LB(int x){
     40     return x&(-x);
     41 }
     42 void upD(int k,int dt){
     43     for(Re int i=k;i<=n;i+=LB(i)){
     44         c[i]+=dt;
     45     }
     46 }
     47 int Qry(int k){
     48     int ans=0;
     49     for(Re int i=k;i>=1;i-=LB(i)){
     50         ans+=c[i];
     51     }
     52     return ans;
     53 }
     54 
     55 void makeA(int lx,int rx){
     56     if(lx>rx)return;
     57     int tp=Qry(rx)-Qry(lx-1);
     58     ans=max(tp,ans);
     59 }
     60 void PickupCandy(){
     61     
     62     X[0]=0; X[n+1]=n+1;
     63     memset(lst,0,sizeof(lst));
     64     memset(c,0,sizeof(c));
     65     
     66     sort(pt+1,pt+n+1,cmpX);
     67     
     68     For(i,1,n){
     69         upD(pt[i].x,1);
     70     }
     71         
     72     For(i,1,n){
     73         int ID=pt[i].id;
     74         int prC=lst[pt[i].cl];
     75         Lc[ID]=prC; Rc[ID]=n+1;
     76         if(prC) Rc[prC]=ID;
     77         makeA(X[prC]+1,X[ID]-1);
     78         lst[pt[i].cl]=ID;
     79     }
     80     For(i,1,Kx){
     81         makeA(X[lst[i]]+1,X[n+1]);
     82     }
     83 
     84     sort(pt+1,pt+n+1,cmpY);
     85     
     86     int Px=1;
     87     For(i,1,n){
     88         while(Px<=n&&pt[i].y==pt[Px].y){
     89             upD(X[pt[Px].id],-1);
     90             Px++;
     91         }
     92         int ID=pt[i].id;
     93         Lc[Rc[ID]]=Lc[ID]; Rc[Lc[ID]]=Rc[ID];
     94         makeA(X[Lc[ID]]+1,X[Rc[ID]]-1);
     95     }
     96     return;
     97 }
     98 
     99 int main(){
    100     //freopen("candy.in","r",stdin);
    101     //freopen("candy.out","w",stdout);
    102     int T; read(T);
    103     while(T--){
    104         read(n); read(Kx);
    105         ans=0;
    106         For(i,1,n){
    107             read(pt[i].x); read(pt[i].y); read(pt[i].cl);
    108             pt[i].id=i;
    109             sX[i]=pt[i].x;
    110         }
    111         sort(sX+1,sX+n+1);
    112         For(i,1,n){
    113             X[i]=lower_bound(sX+1,sX+n+1,pt[i].x)-sX;
    114             pt[i].x=X[i];
    115         }
    116         PickupCandy();
    117         For(i,1,n)pt[i].y*=-1;
    118         PickupCandy();
    119         write(ans); Pn;
    120     }
    121 //    fclose(stdin); fclose(stdout);
    122     return 0;
    123 }
  • 相关阅读:
    Moonlight, 我看行。
    传授犯罪方法罪
    Archos TV+ 1.8.07 照样“越狱”
    写这个月的回忆记,还真少不了学车那点儿事儿
    trigger()与triggerHandler()的不同
    移除不同的
    jq中的效果
    jquery中的文档操作之一addClass append attr
    jquery中的文档操作之四
    toggle方法
  • 原文地址:https://www.cnblogs.com/HLAUV/p/9916248.html
Copyright © 2011-2022 走看看