• 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;  
    } 



  • 相关阅读:
    字符串_操作
    Error: Cannot find module 'webpack-cli/bin/config-yargs'
    ElementUI-Table 表头无法编辑问题
    ElementUI-Cascader组件同时支持懒加载和选择任意一级 问题踩坑
    vue强制刷新子组件
    footer部分,当页面主题内容不满一屏时,始终位于页面底部
    未知宽高的元素水平垂直居中方法总结
    fix元素居中
    link和@import引入css的区别
    Jquery拓展方法
  • 原文地址:https://www.cnblogs.com/herumw/p/9464703.html
Copyright © 2020-2023  润新知