zoukankan      html  css  js  c++  java
  • hdu6089 Rikka with Terrorist

    题意:n*m的平面内有K个不安全点,Q个询问位置在(x,y)的人能走到多少个点?走到:(x,y)和(x',y')之间的矩形中不包含不安全点。

    标程:

     1 #include<bits/stdc++.h>
     2 #define mid ((l+r)>>1)
     3 using namespace std;
     4 int read()
     5 {
     6    int x=0,f=1;char ch=getchar();
     7    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
     8    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
     9    return x*f;
    10 }
    11 const int N=100005;
    12 typedef long long ll;
    13 int n,m,K,Q,T_Max[N<<2],tot,Max;
    14 ll ans[N],T_sum[N<<2],T_suml[N<<2];
    15 struct node{int x,y,id,ty;node(){} node(int a,int b,int c,int d){x=a;y=b;id=c;ty=d;}}a[N*2],dg[N],q[N];
    16 bool cmp(const node &A,const node &B) {return A.x<B.x||A.x==B.x&&A.y<B.y||A.x==B.x&&A.y==B.y&&A.ty<B.ty;}//排序时||不要写成&&! 
    17 ll qry_sum(int k,int l,int r,int L,int R,int &mx)//表示当前区间的右边下界为mx时的折线下面积 
    18 {
    19     if (L<=l&&r<=R)
    20     {
    21         if (mx>=T_Max[k]) return (ll)mx*(r-l+1);   
    22         if (l==r) return mx=T_Max[k]; 
    23         int tt=T_Max[k<<1|1]; ll res=0;
    24         if (mx>=tt)
    25         {
    26            res+=(ll)mx*(r-mid);//mx会被修改,注意统计顺序! 
    27             res+=qry_sum(k<<1,l,mid,L,R,mx);
    28         }else {
    29             res+=T_suml[k];
    30             res+=qry_sum(k<<1|1,mid+1,r,L,R,mx); 
    31         }
    32         mx=T_Max[k]; return res;
    33     }
    34     ll s=0;
    35     if (R>mid) s+=qry_sum(k<<1|1,mid+1,r,L,R,mx);//先走右边,更新下界 
    36     if (L<=mid) s+=qry_sum(k<<1,l,mid,L,R,mx);
    37     return s;
    38 }
    39 void ins(int k,int l,int r,int x,int y)
    40 {
    41     if (l==r)
    42     {
    43         if (y>T_Max[k]) T_Max[k]=T_sum[k]=y;
    44         return; 
    45     }
    46     if (x<=mid) ins(k<<1,l,mid,x,y);else ins(k<<1|1,mid+1,r,x,y);
    47     int tt=T_Max[k<<1|1];
    48     T_suml[k]=qry_sum(k<<1,l,mid,l,mid,tt);//注意如果直接传入T_Max[k<<1|1]的话,在&下会被修改。 
    49     T_Max[k]=max(T_Max[k<<1],T_Max[k<<1|1]); 
    50     T_sum[k]=T_suml[k]+T_sum[k<<1|1];
    51 }
    52 void work()
    53 {
    54     tot=0;
    55     for (int i=1;i<=K;i++) a[++tot]=node(dg[i].x,dg[i].y,i,0);
    56     for (int i=1;i<=Q;i++) a[++tot]=node(q[i].x,q[i].y,i,1);
    57     sort(a+1,a+tot+1,cmp);
    58     for (int i=1;i<=tot;i++)
    59     {
    60         if (!a[i].ty) ins(1,1,m,a[i].y,a[i].x);
    61         else {
    62             Max=0;ans[a[i].id]+=qry_sum(1,1,m,1,a[i].y,Max);//二维数点
    63             Max=0;ans[a[i].id]-=qry_sum(1,1,m,a[i].y,a[i].y,Max);//减去重复的一条同行/同列轴 
    64         }
    65     }
    66 } 
    67 int main()
    68 {
    69     int T=read();
    70     while (T--)
    71     {
    72        n=read();m=read();K=read();Q=read();
    73        for (int i=1;i<=K;i++) dg[i].x=read(),dg[i].y=read();
    74        for (int i=1;i<=Q;i++) q[i].x=read(),q[i].y=read(),ans[i]=0;//组测清零 
    75         for (int i=0;i<4;i++)
    76         {
    77             work();
    78             for (int i=1;i<=(m<<2);i++) T_sum[i]=T_suml[i]=T_Max[i]=0; 
    79             for (int j=1;j<=K;j++) dg[j].x=n-dg[j].x+1,swap(dg[j].x,dg[j].y);//90度旋转坐标 
    80             for (int j=1;j<=Q;j++) q[j].x=n-q[j].x+1,swap(q[j].x,q[j].y); 
    81             swap(n,m);
    82         }
    83         for (int i=1;i<=Q;i++) printf("%lld
    ",(ll)n*m-ans[i]);
    84     } 
    85    return 0;
    86 }

    题解:李超树

    就是为了此神题才去学习了一下李超树。

    以x坐标的移动来看可以到达的点的范围,从起点轴向两边形成不规则菱形。

    分四块讨论,以左下角为例,线段树上的点为y坐标,维护递减折线。左区间的高度要大于等于右区间,所以更新的时候要把右区间的高度也维护进左区间。求折线下面积和的时候,维护一个右方高度下界,先统计右区间再统计左区间。

  • 相关阅读:
    在应用程序中利用Jena API处理OWL本体
    Encoded vs Literal, RPC vs Document
    DWR、XMLHTTP、XMLRPC和Flex
    北京的第一场雪
    让IE浏览器提示下载或直接打开word文档
    色拉英语第一集第一幕:记得说“请”
    色拉英语第一集第三幕:凯文在家吗?
    30天敏捷结果(30):提升敏捷结果
    生活:兔年春节家庭寻宝习俗
    敏捷个人:2011/1/26聊天记录(沟通、优势)
  • 原文地址:https://www.cnblogs.com/Scx117/p/9115327.html
Copyright © 2011-2022 走看看