zoukankan      html  css  js  c++  java
  • 【BZOJ 4662】 4662: Snow (线段树+并查集)

    4662: Snow

    Time Limit: 40 Sec  Memory Limit: 256 MB
    Submit: 136  Solved: 47

    Description

    2333年的某一天,临冬突降大雪,主干道已经被雪覆盖不能使用。城
    主 囧·雪 决定要对主干道进行一次清扫。
    临冬城的主干道可以看为一条数轴。囧·雪 一共找来了n个清理工,第
    i个清理工的工作范围为[li,ri],也就是说这个清理工会把[li,ri]这一
    段主干道清理干净(当然已经被清理过的部分就被忽略了)。当然有可能主
    干道不能全部被清理干净,不过这也没啥关系。
    虽然 囧·雪 啥都不知道,但是他还是保证了不会出现某一个清理工的
    工作范围被另一个清理工完全包含的情况(不然就太蠢了)。
    作为临冬城主,囧·雪 给出了如下的清扫方案:
    在每一天开始的时候,每一个还没有工作过的清理工会观察自己工作
    范围内的道路,并且记下工作范围内此时还没有被清理的道路的长度(称
    为这个清理工的工作长度)。然后 囧·雪 会从中选择一个工作长度最小的
    清理工(如果两个清理工工作长度相同,那么就选择编号小的清理工)。然
    后被选择的这个清理工会清理自己的工作范围内的道路。为了方便检查工
    作质量,囧·雪 希望每一天只有一个清理工在工作。
    你要注意,清理工的工作长度是可能改变的,甚至有可能变成0。尽管
    如此,这个清理工也还是会在某一天工作。
    现在,囧·雪 想要知道每一天都是哪个清理工在工作?

    Input

    第一行两个整数t,n。分别表示主干道的长度(也就是说,主干道是数
    轴上[1,t]的这一段)以及清理工的人数。
    接下来n行,每行两个整数li,ri。意义如题。
    n<=3*10^5, 1<=li<ri<=t<=10^9,保证输入的li严格递增

    Output

    输出n行,第i行表示第i天工作的清理工的编号。

    Sample Input

    15 4
    1 6
    3 7
    6 11
    10 14

    Sample Output

    2
    1
    3
    4

    HINT

    Source

    【分析】

      其实这个也是线段树的经典了吧。

      之前做过好几题,就是每次操作的时候都会有一个节点删掉以后彻底没用,这样即使暴力也是不会超时的,因为每个点只会用一次。

      这里的这个点就是每个清洁工,我们只会询问他一次。

      跳出清扫区间这个圈子,用清洁工来建线段树。

      因为当你修改某段区间的时候,受影响的清洁工也是一个区间。

      先离散化,然后暴力删去区间,用并查集快速跳去已经失效的区间,每个位置只会操作一次,是可以过的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 300010
      8 #define INF 0x7fffffff
      9 
     10 int nl[Maxn],nr[Maxn],nn[Maxn*2];
     11 
     12 struct node
     13 {
     14     int l,r,lc,rc,mn,lazy;
     15     int id;
     16 }tr[Maxn*2];
     17 
     18 int rt[Maxn*2];
     19 int rtt(int x)
     20 {
     21     if(rt[x]!=x) rt[x]=rtt(rt[x]);
     22     return rt[x];
     23 }
     24 
     25 int len=0;
     26 int build(int l,int r)
     27 {
     28     int x=++len;
     29     tr[x].l=l;tr[x].r=r;
     30     if(l!=r)
     31     {
     32         int mid=(l+r)>>1;
     33         tr[x].lc=build(l,mid);
     34         tr[x].rc=build(mid+1,r);
     35         tr[x].lazy=0;
     36         int lc=tr[x].lc,rc=tr[x].rc;
     37         if(tr[lc].mn<=tr[rc].mn) tr[x].mn=tr[lc].mn,tr[x].id=tr[lc].id;
     38         else tr[x].mn=tr[rc].mn,tr[x].id=tr[rc].id;
     39     }
     40     else tr[x].lc=tr[x].rc=0,tr[x].mn=nn[nr[l]]-nn[nl[l]],tr[x].id=l;
     41     return x;
     42 }
     43 
     44 void upd(int x)
     45 {
     46     if(tr[x].l==tr[x].r) return;
     47     int lc=tr[x].lc,rc=tr[x].rc;
     48     if(tr[lc].mn!=INF) tr[lc].mn-=tr[x].lazy;
     49     if(tr[rc].mn!=INF) tr[rc].mn-=tr[x].lazy;
     50     tr[lc].lazy+=tr[x].lazy;
     51     tr[rc].lazy+=tr[x].lazy;
     52     tr[x].lazy=0;
     53 }
     54 
     55 void change(int x,int y,int p)
     56 {
     57     if(tr[x].mn==INF) return;
     58     int mid=(tr[x].l+tr[x].r)>>1,lc=tr[x].lc,rc=tr[x].rc;
     59     if(p)
     60     {
     61         if(nl[tr[x].l]<=y&&y<nr[tr[x].l]&&nl[tr[x].r]<=y&&y<nr[tr[x].r])
     62         {
     63             tr[x].lazy+=nn[y+1]-nn[y];
     64             tr[x].mn-=nn[y+1]-nn[y];
     65             return;
     66         }
     67         if(tr[x].l==tr[x].r) return;
     68         upd(x);
     69         if(y<nr[mid]) change(lc,y,p);
     70         if(nl[mid+1]<=y) change(rc,y,p);
     71     }
     72     else
     73     {
     74         if(tr[x].l==tr[x].r)
     75         {
     76             tr[x].mn=INF;
     77             return;
     78         }
     79         upd(x);
     80         if(y<=mid) change(tr[x].lc,y,p);
     81         else change(tr[x].rc,y,p);
     82     }
     83     if(tr[lc].mn<=tr[rc].mn) tr[x].mn=tr[lc].mn,tr[x].id=tr[lc].id;
     84     else tr[x].mn=tr[rc].mn,tr[x].id=tr[rc].id;
     85 }
     86 
     87 
     88 struct nnode{int x,id;}t[Maxn*2];
     89 bool cmp(nnode x,nnode y) {return x.x<y.x;}
     90 
     91 int main()
     92 {
     93     int mx,n;
     94     scanf("%d%d",&mx,&n);
     95     for(int i=1;i<=n;i++) {scanf("%d%d",&nl[i],&nr[i]);
     96                       t[i*2-1].x=nl[i];t[i*2-1].id=i;t[i*2].x=nr[i];t[i*2].id=-i;}
     97     sort(t+1,t+1+2*n,cmp);
     98     mx=1;nl[t[1].id]=1;nn[1]=t[1].x;
     99     for(int i=2;i<=2*n;i++)
    100     {
    101         if(t[i].x!=t[i-1].x) mx++,nn[mx]=t[i].x;
    102         if(t[i].id>0) nl[t[i].id]=mx;
    103         else nr[-t[i].id]=mx;
    104     }
    105     build(1,n);
    106     for(int i=1;i<=mx;i++) rt[i]=i;
    107     for(int i=1;i<=n;i++)
    108     {
    109         int x=tr[1].id;
    110         printf("%d
    ",x);
    111         change(1,x,0);
    112         int st=rtt(nl[x]);
    113         for(int j=st;j<nr[x];)
    114         {
    115             change(1,j,1);
    116             rt[j]=rtt(j+1);
    117             j=rt[j];
    118         }
    119     }
    120     return 0;
    121 }
    View Code

    2017-03-27 09:29:36

  • 相关阅读:
    【足迹C++primer】46、动态存储类
    java foreach循环为什么不能赋值
    使用apktool解包和打包apk
    杭电 HDU ACM Milk
    [SQL基础]入门
    [c#基础]泛型集合的自定义类型排序
    [Asp.net]常见word,excel,ppt,pdf在线预览方案,有图有真相,总有一款适合你!(续)
    [c#基础]使用抽象工厂实现三层
    [c#基础]DataTable的Select方法
    Winform模拟post请求和get请求登录网站
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6625209.html
Copyright © 2011-2022 走看看