zoukankan      html  css  js  c++  java
  • 杭电多校第4场 1008(hdu 6992

    题意:给定一张n*m的方格,起点在左上角,只能向下或向右走,地图中有k个地雷,人不能走到地雷上,问可能到达的点有多少。

    很明显,这道题的数据很大,我们直接处理整张图肯定不行,而k很小,所以我们得从地雷入手,求哪些点走不到。

    而因为我们的人只能向下向右,所以当一个点本身为地雷且(x-1,y+1)也有地雷,那说明这两点包夹的那个点也走不到,如图:

     圆圈为给出的地雷位置,叉叉是实际上同样走不到的点。

    那么我们不妨对地雷的位置按照行优先排序,对于每一行的地雷,我们只需要知道上一行从(x-1,y+1)开始有连续的多少个地雷,就能求出在这一行中对应的地雷会产生多少无法到达的点。这时不难想到要用线段树来维护。

    注意因为x=0与y=0处默认是无法到达的,所以我们可以通过将线段树初值设为1(无法到达)来解决x=0,通过加入n-1个点(k,0)来解决m=0的点。

    这里(1,0)是没有必要加入的,因为不可能与输入的地雷产生互动,记得在计算答案时减掉即可。

    下附代码:

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 using namespace std;
      4 ll n,m,k;
      5 struct seg_tree{
      6     #define p2 (p<<1)
      7     #define p3 ((p<<1)|1)
      8     ll tr[400005],lz[400005];
      9     void build(int l,int r,int p){
     10         if(l==r){
     11             tr[p]=1;
     12             lz[p]=-1;
     13             return ;
     14         }
     15         int mid=(l+r)>>1;
     16         build(l,mid,p2);
     17         build(mid+1,r,p3);
     18         tr[p]=tr[p2]+tr[p3];
     19         lz[p]=-1;
     20     }
     21     void push_down(int l,int r,int p){
     22         if(lz[p]!=-1){
     23             int mid=(l+r)>>1;
     24             tr[p2]=lz[p]*(mid-l+1);
     25             tr[p3]=lz[p]*(r-mid);
     26             lz[p2]=lz[p3]=lz[p];
     27             lz[p]=-1;
     28         }
     29     }
     30     void update(int l,int r,int le,int ri,int p,int val){
     31         if (l==le && ri==r){
     32             tr[p]=val*(r-l+1);
     33             lz[p]=val;
     34             return ;
     35         }
     36         if(lz[p]!=-1) push_down(l,r,p);
     37         int mid=(l+r)>>1;
     38         if(ri<=mid) update(l,mid,le,ri,p2,val);
     39         else if(le>mid) update(mid+1,r,le,ri,p3,val);
     40         else update(l,mid,le,mid,p2,val),update(mid+1,r,mid+1,ri,p3,val);
     41         tr[p]=tr[p2]+tr[p3];
     42     }
     43     ll query(int l,int r,int le,int ri,int p){
     44         if(l==le && r==ri && tr[p]==r-l+1)
     45             return tr[p];
     46         if (l==r) return 0;
     47         if(lz[p]!=-1) push_down(l,r,p);
     48         int mid=(l+r)>>1,ret=0;
     49         if (ri<=mid) ret=query(l,mid,le,ri,p2);
     50         else if (le>mid) ret=query(mid+1,r,le,ri,p3);
     51         else {
     52             int q1=query(l,mid,le,mid,p2);
     53             if (q1==(mid-le+1)) ret=q1+query(mid+1,r,mid+1,ri,p3);
     54             else ret=q1;
     55         }
     56         return ret;
     57     }
     58 } tr;
     59 struct node{
     60     int x,y;
     61 }a[200005];
     62 vector<pair<int,int>> vet;
     63 bool cmp(node x,node y){
     64     if (x.x!=y.x) return x.x<y.x;
     65     else return x.y<y.y;
     66 }
     67 int main(){
     68   //  freopen("1008.in","r",stdin);
     69    // freopen("1.out","w",stdout);
     70     int T;
     71     scanf("%d",&T);
     72     while (T--){
     73         scanf("%lld%lld%lld",&n,&m,&k);
     74         for (int i=1; i<=k; i++){
     75             scanf("%d%d",&a[i].x,&a[i].y);
     76         }
     77         for (int i=2; i<=n; i++){
     78             a[k+i-1].x=i,a[k+i-1].y=0;
     79         }
     80         k+=n-1;
     81         sort(a+1,a+1+k,cmp);
     82         tr.build(0,m,1);
     83         ll ret=0,st=1;
     84         for (int i=1; i<=n; i++){
     85             int ed=-1;
     86             ll sum=0;
     87             vet.clear();
     88             while (a[st].x==i && st<=k){
     89                 if (a[st].y<=ed) {
     90                     st++;
     91                     continue;
     92                 }
     93                 ll tmp;
     94                 if (a[st].y==m) tmp=0;
     95                 else tmp=tr.query(0,m,a[st].y+1,m,1);
     96                 vet.push_back({a[st].y,a[st].y+tmp});
     97                 ed=a[st].y+tmp;
     98                 sum+=tmp+1;
     99                 st++;
    100             }
    101             ret+=sum;
    102             tr.update(0,m,0,m,1,0);
    103             for (auto j:vet){
    104                 tr.update(0,m,j.first,j.second,1,1);
    105             }
    106         }
    107         printf("%lld
    ",n*(m+1)-ret-1);
    108     }
    109 }
    110 
    111 /*7 7 8
    112 2 3
    113 2 5
    114 3 2
    115 3 6
    116 5 2
    117 5 6
    118 6 3
    119 6 5
    120 */
    View Code
  • 相关阅读:
    PHP迭代生成器---yield
    array_chunk — 将一个数组分割成多个
    php array_change_key_case
    PHP trait介绍
    mysql视图
    mysql常见内置函数
    MySQL表复制
    二分查找算法(折半查找算法)
    使用SplFixedArray创建固定大小的数组
    Frameset Example
  • 原文地址:https://www.cnblogs.com/i-caigou-TT/p/15079607.html
Copyright © 2011-2022 走看看