zoukankan      html  css  js  c++  java
  • hdu1540-Tunnel Warfare-(线段树+二分)

    题意:有n个村庄排成一列,相邻的村庄可以通信,炸毁则不可以通信,进行m个操作。3种操作,1.炸毁某村庄;2.修复上一个被炸毁的村庄;3.查询某个村庄能通信的村庄数(自己算一个)。

    解题:求某个点左边扩散和右边扩散的区间和,没被炸毁就算1,炸毁则算0,用二分查找左边界和右边界,假设查询的点为x,则左边界是x-l+1=query(),右边界判断标准是r-x+1=query();两次二分log,查询query也是log,时间复杂度是O(n+m*log*log),限速2000ms,1600+ms,思路简单,勉强能过。

    另外还有一个坑:一个村庄可以被多次炸毁,修复只需要一次就够了。

      1 #include<stdio.h>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<math.h>
      6 #include<string>
      7 #include<map>
      8 #include<queue>
      9 #include<stack>
     10 #include<set>
     11 #define ll long long
     12 #define inf 0x3f3f3f3f
     13 using namespace std;
     14 
     15 int n,m;
     16 int a[50005];
     17 int sum[50005*4];
     18 stack<int>sta;
     19 
     20 void build(int l,int r,int rt)
     21 {
     22     if(l==r)
     23     {
     24         sum[rt]=a[l];
     25         return;
     26     }
     27     int mid=(l+r)/2;
     28     build(l,mid,rt*2);
     29     build(mid+1,r,rt*2+1);
     30 
     31     sum[rt]=sum[rt*2]+sum[rt*2+1];
     32 }
     33 
     34 void update(int p,int c,int l,int r,int rt)
     35 {
     36     if(l==r)///到达叶节点,修改后返回
     37     {
     38         sum[rt]=sum[rt]+c;
     39         return ;
     40     }
     41     int mid=(l+r)/2;
     42     ///根据条件判断往左调用还是往右
     43     if(p<=mid) update(p,c,l, mid, rt*2);
     44     else     update(p,c,mid+1, r, rt*2+1);
     45     sum[rt] = sum[rt*2] + sum[rt*2+1];
     46 }
     47 
     48 int query(int L,int R,int l,int r,int rt)
     49 {
     50     if(L<=l&&r<=R)///在区间内,直接返回
     51         return sum[rt];
     52 
     53     int m=(l+r)/2;
     54 
     55     ///累计答案
     56     int ans=0;
     57     if(L<=m) ans=ans+query(L,R,l,m,rt*2);
     58     if(R>m)  ans=ans+query(L,R,m+1,r,rt*2+1);
     59 
     60     return ans;
     61 }
     62 
     63 int main()
     64 {
     65     while(scanf("%d%d",&n,&m)!=EOF)
     66     {
     67         while(!sta.empty())
     68             sta.pop();
     69         set<int>se;
     70         for(int i=1;i<=n;i++)
     71             a[i]=1;
     72         build(1,n,1);
     73         char c;
     74         while(m--)
     75         {
     76             getchar();
     77             scanf("%c",&c);
     78             int x;
     79             if(c=='D')
     80             {
     81                 scanf("%d",&x);
     82                 if(a[x]!=0)
     83                     update(x,-1,1,n,1);
     84                 a[x]=0;
     85                 sta.push(x);
     86             }
     87             else if(c=='R')
     88             {
     89                 x=sta.top();
     90                 if( a[x]==0 );
     91                 else
     92                 {
     93                     while( a[x]!=0 )
     94                     {
     95                         sta.pop();
     96                         x = sta.top();
     97                     }
     98                 }
     99                 sta.pop();
    100                 a[x]=1;
    101                 update(x,1,1,n,1);
    102             }
    103             else
    104             {
    105                 int ans=0;
    106                 scanf("%d",&x);
    107 
    108                 if(a[x]!=0)
    109                 {
    110                     int l=1,r=x,res1=-1,res2=-1;
    111                     while(l<=r)///往左找最大连通的村庄数
    112                     {
    113                         int mid=(l+r)/2;
    114                         if( query(mid,x,1,n,1)==x-mid+1 )///二分内往左找mid
    115                         {
    116                             res1=mid;
    117                             r=mid-1;
    118 
    119                         }
    120                         else///二分内往右找
    121                         {
    122                             l=mid+1;
    123                         }
    124                     }
    125                     l=x,r=n;
    126                     while(l<=r)
    127                     {
    128                         int mid=(l+r)/2;
    129 
    130                         if( query(x,mid,1,n,1)==mid-x+1 )
    131                         {
    132                             res2=mid;
    133                             l=mid+1;
    134                         }
    135                         else
    136                             r=mid-1;
    137                     }
    138                     printf("%d
    ",res2-res1+1);
    139                 }
    140                 else
    141                     printf("0
    ");
    142             }
    143         }
    144 
    145     }
    146 
    147     return 0;
    148 }
    149 /**
    150 5 12
    151 D 3
    152 D 2
    153 D 1
    154 D 1
    155 D 2
    156 R
    157 R
    158 R
    159 Q 1
    160 Q 2
    161 Q 3
    162 Q 4
    163 */
  • 相关阅读:
    Informix日期获取上周上月昨天去年SQL
    PDI-KETTLE-4 使用Kettle完成通用DB生成指定文件并通过FTP上传
    日常问题解决记录二:DOS下切换盘符和工作目录
    PDI-KETTLE-3:数据库连接
    window下安装node.js
    【原创】正则断言的使用--为自动生成的get方法添加注解字段
    【原创】文本工具的使用--根据数据库字段快速生成该表对应的Model类属性
    【原创】字符串工具类--驼峰法与下划线法互转
    【原创】字符串工具类--获取汉字对应的拼音(全拼或首字母)
    【原创】关于oracle11G空表无法导出问题的解决方法
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/11206632.html
Copyright © 2011-2022 走看看