毯子 题解(COCI 2008-2009Final C)

来源:互联网 发布:淘宝计划书范文 编辑:程序博客网 时间:2024/06/02 19:41

[题意]

N 块矩形毯子铺在地上。0秒时(0,0)处有一桶油倒了,然后开始流呀流,每秒往八个方向扩散一个单位。注意,这里的坐标描述一个单元格,不表示点。M个询问,每次问一个时间点被油染到的毯子面积(若有毯子重叠,面积也要累加,如一个单位格被三个毯子覆盖,那么被油染到之后就算3个单位面积)。

[思路]

50分:暴力!n*m枚举每个询问时每块毯子被染到的范围.直接把顶点算出.

100分:

     有两个切入点:

1)每块毯子被染的区域增量随时间改变是有规律的:

     可以分成两个部分:

第一部分是一个公差为2的等差数列:如图所示,增量分别是3,5,7块;

第二部分是一个常数列:图中的常数为3.

每个部分都是一个独立的区间.

2)每块毯子染到的面积是独立的,可以叠加.

确定了以上的两点, 就可以联想到刷漆.把每个时间点的状态叠加.

每个时间点的状态由两个变量来表示:b,k.b表示当前时间点的染到的面积增量的值,k表示当前时间点染到的面积增量的公差.

对于每个时间点t对t-1的增量就可以表示为:b+k+b[t](b[t],表示t时间点的面积增量)

优化:

因为油的变化趋势是随原点对称的,所以把所有矩形都翻到右上角去,

可以在刷漆时更简便.

注意:

1. 输入数据有负数,慎用读入挂

2. 在翻折矩形之后,矩形的个数增加了,数组比忘了开大点!!

 

[启发]

1.    对于询问类的问题可以离线做.

2.   随时间增长的变量可以找规律,挖性质.

<span style="font-family:Comic Sans MS;font-size:18px;">#include<cstdio>#include<iostream>#include<algorithm>#include<vector>#include<map>#define ll long longusing namespace std;inline void rd(int &res){    res=0;    int k=1;char c;    while(c=getchar(),c<48&&c!='-');    if(c=='-'){k=-1;c=getchar();}    do{        res=(res<<1)+(res<<3)+(c^48);    }while(c=getchar(),c>=48);    res*=k;}inline void print(ll k){    if(k==0)return ;    print(k/10);    putchar((k%10)^48);}inline void sc(ll k){    print(k);    if(k==0)putchar('0');    putchar('\n');}const int M=100005;const int N=1e6+5;struct node{int x1,y1,x2,y2;}A[M*4],B[M*4];int n,m;ll res[N];struct LAY{ll b,k;};vector<LAY>brush[N];void add(int t,ll b,ll k){//b表示常量,k表示增量      brush[t].push_back((LAY){b,k});}void solve(){    int i,j,k,tot=0,now=n;    for(i=1;i<=now;i++){//矩形反转         int x1=A[i].x1,x2=A[i].x2,y1=A[i].y1,y2=A[i].y2;        if(x1>=0&&x2>=0&&y1>=0&&y2>=0){            B[++tot]=(node){x1,y1,x2,y2};continue;        }           if(x1<0){            if(x2<0) A[++now]=(node){-x2,y1,-x1,y2};            else {                A[++now]=(node){1,y1,-x1,y2};//分成两块                A[++now]=(node){0,y1,x2,y2};            }            continue;        }        else if(x1>=0&&x2>=0&&y1<0){            if(y2<0)B[++tot]=(node){x1,-y2,x2,-y1};            else {                B[++tot]=(node){x1,0,x2,y2};                B[++tot]=(node){x1,1,x2,-y1};            }        }    }    for(i=1;i<=tot;i++){        int x1=B[i].x1,x2=B[i].x2,y1=B[i].y1,y2=B[i].y2;        int t1,t2,t3;        ll s1,s2;        t1=max(x1,y1);        t2=min(x2,y2);        t3=max(x2,y2);//算出两个部分分别的时间点        s1=1ll*(min(x2,t1)-max(x1,0)+1)*(min(y2,t1)-max(y1,0)+1);        if(x2>y2)s2=y2-y1+1;        else s2=x2-x1+1;        if(t2<t1)t2=t1;        add(t1,s1,2);//刷漆:第一部分初始值为s1,公差为2        add(t2+1,-s1-1ll*(t2-t1+1)*2,-2);//结束时把第一部分增加的值减去        add(t2+1,s2,0);//常量部分        add(t3+1,-s2,0);    }    ll b=0,plus=0,ans=0;    for(i=0;i<N;i++){        b+=plus;//公差        for(j=0;j<brush[i].size();j++){            b+=brush[i][j].b;plus+=brush[i][j].k;//刷漆累加        }        ans+=b;        res[i]=ans;    }}int main(){    rd(n);    int t;    for(int i=1;i<=n;i++){        rd(A[i].x1);rd(A[i].y1);        rd(A[i].x2);rd(A[i].y2);    }    solve();    rd(m);    for(int i=1;i<=m;i++){        rd(t);        sc(res[t]);    }    return 0;}
20160625离线赛/COCI 2008-2009FinalC


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 南充市住房公积金管理中心 南宁住房公积金 晋中住房公积金查询个人账户 保定住房公积金查询 淮南市住房公积金查询 苏州市住房公积金管理中心 宜春市住房公积金管理中心 住房公积金管理中心电话 福州住房公积金查询 玉林住房公积金查询 住房公积金管理中心地址 烟台住房公积金查询个人账户 个人住房公积金余额查询 成都市住房公积金中心 东莞住房公积金个人帐户查询 西安市住房公积金查询 黄石住房公积金查询 住房公积金客服电话 保定住房公积金 郑州住房公积金 住房公积金咨询电话 泉州市住房公积金个人查询 南充住房公积金查询个人账户 住房公积金电话号码 银川住房公积金查询 淮南住房公积金查询个人账户 毕节住房公积金查询 邯郸市住房公积金管理中心 渭南市住房公积金管理中心 连云港住房公积金 临沂住房公积金查询个人账户 南充住房公积金 住房公积金密码 运城住房公积金查询 住房公积金查询电话 住房公积金热线 昆明市住房公积金管理中心 乌鲁木齐住房公积金查询 玉林市住房公积金管理中心 南宁住房公积金网 宜宾市住房公积金管理中心