zoukankan      html  css  js  c++  java
  • hdu4533 威威猫系列故事——晒被子

    Problem Description
      因为马拉松初赛中吃鸡腿的题目让不少人抱憾而归,威威猫一直觉得愧对大家,这几天他悄悄搬到直角坐标系里去住了。
      生活还要继续,太阳也照常升起,今天,威威猫在第一象限晒了N条矩形的被子,被子的每条边都和坐标轴平行,不同被子的某些部分可能会叠在一起。这时候,在原点处突然发了场洪水,时间t的时候,洪水会蔓延到( t, t ),即左下角为( 0, 0 ) ,右上角为( t, t )的矩形内都有水。
      悲剧的威威猫想知道,在时间t1, t2, t3 ... tx 的时候,他有多少面积的被子是湿的?
     

    Input
    输入数据首先包含一个正整数T,表示有T组测试数据;
    每组数据的第一行首先是一个整数N,表示有N条被子;
    接下来N行,每行包含四个整数x1, y1, x2, y2,代表一条被子的左下角和右上角的坐标;
    然后接下来一行输入一个整数x,表示有x次询问;
    再接下来x行,输入x个严格单调递增的整数,每行一个,表示威威猫想知道的时间ti。

    [Technical Specification]
    T <= 5
    0 < N <= 20000
    1 <= x1 < x2 <= 200000
    1 <= y1 < y2 <= 200000
    1 <= x <= 20000
    1 <= ti <= 200000 (1 <= i <= x )
     

    Output
    对于每次询问,请计算并输出ti时有多少面积的被子是湿的,每个输出占一行。
     

    Sample Input
    1 2 1 1 3 3 2 2 4 4 5 1 2 3 4 5
     

    Sample Output
    0 1 5 8 8

    这题里求的面积是各个矩形的面积和,并不是矩形面积的并,即相互不影响,因为对于各个时段,矩形的面积都可以用A*t^2+B*t+C表示,所以我们可以用树状数组或者线段树分别维护A,B,C,每次读入一个矩形,就记录它对不同时间段t的影响,然后把相应的系数加到线段树中。

    当一个矩形读入时(左下角坐标(x1,y1),右上角坐标(x2,y2)),有四种影响情况:

    1.0~max(x1,y1) 这个时期因为t时间形成的矩形在该矩形下面,对面积没有影响,所以不用考虑。

    2.如果存在t时间形成的矩形部分覆盖该矩形,但没有碰到或者超过该矩形的上边或者右边,那么要同时更新A,B,C,表达式为(t-x1)*(t-y1)。这里的判断表达式为如果(max(x1,y1)<min(x2,y2)),则更新max(x1,y1)~min(x2,y2)。

    3.t时间内形成的矩形恰好碰到或者越过右边或上边的一条,即这段时间内的矩形面积变化中(x2-x1)或(y2-y1)为常数,那么要更新,注意,这里更新的时候要分类讨论,具体看代码。

    4.max(x2,y2)~maxn,这个时期因为t时间形成的矩形已经完全覆盖矩形,所以要更新C,加上面积常数。

    写线段树的时候注意,三个变量要一起存,不能开三个线段树,会超内存的。

    线段树代码:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define ll __int64
    #define maxn 200050
    ll A,B,C;
    ll a[10];
    struct node{
        ll l,r,cnt1,cnt2,cnt3,flag;
    }b[4*maxn];
    
    void build(ll l,ll r,ll i)
    {
        ll mid;
        b[i].l=l;b[i].r=r;b[i].cnt1=b[i].cnt2=b[i].cnt3=0;b[i].flag=1;
        if(l==r)return;
        mid=(l+r)/2;
        build(l,mid,i*2);
        build(mid+1,r,i*2+1);
    }
    void update(ll l,ll r,ll a[],ll i)
    {
        ll mid;
        if(b[i].l==l && b[i].r==r){
            b[i].cnt1+=a[1];b[i].cnt2+=a[2];b[i].cnt3+=a[3];return;
        }
        mid=(b[i].l+b[i].r)/2;
        if(r<=mid)update(l,r,a,i*2);
        else if(l>mid)update(l,r,a,i*2+1);
        else{
            update(l,mid,a,i*2);
            update(mid+1,r,a,i*2+1);
        }
    }
    
    void question(ll id,ll i)
    {
        ll mid;
        if(b[i].l==id && b[i].r==id){
            A=b[i].cnt1;B=b[i].cnt2;C=b[i].cnt3;return;
        }
        if(b[i].cnt1){
            b[i*2].cnt1+=b[i].cnt1;
            b[i*2+1].cnt1+=b[i].cnt1;
            b[i].cnt1=0;
        }
        if(b[i].cnt2){
            b[i*2].cnt2+=b[i].cnt2;
            b[i*2+1].cnt2+=b[i].cnt2;
            b[i].cnt2=0;
        }
        if(b[i].cnt3){
            b[i*2].cnt3+=b[i].cnt3;
            b[i*2+1].cnt3+=b[i].cnt3;
            b[i].cnt3=0;
        }
        mid=(b[i].l+b[i].r)/2;
        if(id<=mid)question(id,i*2);
        else question(id,i*2+1);
    }
    
    int main()
    {
        ll i,j,x1,x2,y1,y2,t,t1,t2;
        int T,n,m;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            build(1,maxn,1);
            for(i=1;i<=n;i++){
                scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);
                if(max(x1,y1)<min(x2,y2)){
                    a[1]=1;a[2]=-(x1+y1);a[3]=x1*y1;
                    update(max(x1,y1),min(x2,y2)-1,a,1);
                }
      
                if(x2<y2){
                    a[1]=0;a[2]=-x1+x2;a[3]=y1*(x1-x2);
                    update(max(x2,y1),y2-1,a,1);  
                }
                if(y2<x2){
                    a[1]=0;a[2]=-y1+y2;a[3]=x1*(y1-y2);
                    update(max(y2,x1),x2-1,a,1);  
                }
                a[1]=0;a[2]=0;a[3]=(x2-x1)*(y2-y1);
                update(max(x2,y2),maxn,a,1);
                
            }
            scanf("%d",&m);
            for(i=1;i<=m;i++){
                scanf("%I64d",&t);
                A=B=C=0;
                question(t,1);
                printf("%I64d
    ",A*t*t+B*t+C);
            }
        }
        return 0;
    }


    树状数组代码://速度快了一倍= =

    #include <iostream>  
    #include <cstdio>  
    #include <cstring> 
    #define maxn 200010  
    #define ll __int64 
    using namespace std;
    ll max(ll a,ll b){
    	return a>b?a:b;
    }
    ll min(ll a,ll b){
    	return a<b?a:b;
    }
    
    
    struct segment{
    	ll b[maxn],ans;
    	void clear(){
    		memset(b,0,sizeof(b));
    	}
    	int lowbit(ll x){
    		return x&(-x);
    	}
    	void update(ll pos,ll num){
    		while(pos<=maxn){
    			b[pos]+=num;pos+=lowbit(pos);
    		}
    	}
    	ll getsum(ll pos){
    		ans=0;
    		while(pos>0){
    			ans+=b[pos];pos-=lowbit(pos);
    		}
    		return ans;
    	}
    }A,B,C;
    
    void fun(ll l,ll r,ll num1,ll num2,ll num3){
    	A.update(l,num1);A.update(r+1,-num1);
    	B.update(l,num2);B.update(r+1,-num2);
    	C.update(l,num3);C.update(r+1,-num3);
    }
    
    int main()  
    {  
      
        int t;  
        scanf("%d",&t);  
        while(t--)  
        {  
            A.clear(); B.clear(); C.clear();  
           int n,m;  
            scanf("%d",&n);  
            for(int i=0;i<n;i++)  
            {  
                ll x1,y1,x2,y2;  
                scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);  
      
                if(max(x1,y1)<min(x2,y2))  
                    fun(max(x1,y1),min(x2,y2),1,-(x1+y1),x1*y1);  
      
                if(x2<y2) fun(max(x2,y1)+1,y2,0,-x1+x2,y1*(x1-x2));  
                if(y2<x2) fun(max(y2,x1)+1,x2,0,-y1+y2,x1*(y1-y2));  
      
                fun(max(x2,y2)+1,maxn,0,0,(x2-x1)*(y2-y1));  
            }  
      
            scanf("%d",&m);  
            while(m--)  
            {  
                ll t;  
                scanf("%I64d",&t);  
                ll ans=0;  
                ans+=A.getsum(t)*t*t;  
                ans+=B.getsum(t)*t;  
                ans+=C.getsum(t);  
      
                printf("%I64d
    ",ans);  
            }  
        }  
        return 0;  
    } 



  • 相关阅读:
    hdu5728 PowMod
    CF1156E Special Segments of Permutation
    CF1182E Product Oriented Recurrence
    CF1082E Increasing Frequency
    CF623B Array GCD
    CF1168B Good Triple
    CF1175E Minimal Segment Cover
    php 正则
    windows 下安装composer
    windows apache "The requested operation has failed" 启动失败
  • 原文地址:https://www.cnblogs.com/herumw/p/9464703.html
Copyright © 2011-2022 走看看