hdu 4533 威威猫系列故事——晒被子(两种方法)
来源:互联网 发布:市场营销网络 编辑:程序博客网 时间:2024/04/28 14:49
方法一:
把(0,0),(t,t)看成是一个大矩形的话,那么这个大矩形的右上坐标x是等于y的,有了这个就好办了,
我们可以维持一颗关于t的线段树,比如现在对一个X矩形(x1,y1),(x2,y2)来说如果t>=Max(x2,y2),那么这个面积直接加上;
在关于t的这颗线段树上操作也就是相当于更新(Max(x2,y2)~Max(t))这个区间,而对于(0~MAx(x1,y1))这个区间是无影响的;
现在在于怎么处理MAx(x1,y1)~Min(x2,y2)和Max(MAx(x1,y2),Min(x2,y2))~Max(x2,y2)这两个区间
如果Max(x1,y2)<Min(x2,y2),那么这端区间和X矩形的相交的面积就是(t-x1)*(t-y1);而这里t是变动的,
所以我把式子变一下得t*t-(x1+y1)*t+x1*y1,这样我们可以开三个数组保存这个方程的系数(1,-(x1+y1),x1*y1),
因为这三个系数是常数并且可以进行加减运算,然后一样可以利用线段树的lazy思想,系数到最后再计算是一样的。
用类似的方法去处理Max(MAx(x1,y2),Min(x2,y2))~Max(x2,y2)这个区间,画个图就明白了;
对于Max(MAx(x1,y2),Min(x2,y2))~Max(x2,y2)这个区间处理有两种情况(如下图,手画的,只能看个大概):
这是第一种情况(y2>x2):
重叠面积为(t-x1)*(t-y1)-(t-x2)*(t-y1)展开为:(-x1-y1+y1+x2)*t+y1*(x1-x2);和前面一样在线段树区间上更新这个方程的系数
第二种情况(x2>y2):
重叠面积为(t-x1)*(t-y1)-(t-x1)*(t-y2)展开为:(-x1-y1+x1+y2)*t+x1*(y1-y2);和前面一样在线段树区间上更新这个方程的系数
上面的介绍体现在POP函数里面,主要的思想是利用保存系数达到目的;
今天比赛太挫了,A题弄了我好久wa了好几次,D题也没在比赛的时候过,太悲剧了;
#include<stdio.h>
#include<string.h>#define _LL __int64
int n=200000;
_LL A[800000],B[800000],C[800000];
void update(int i,int l,int r,int a,int b,_LL *v)
{
int mid;
if(a>b) return;
if(a==l&&r==b)
{
A[i]+=v[0];B[i]+=v[1];C[i]+=v[2];
return ;
}
mid=(l+r)/2;
if(b<=mid) update(i<<1,l,mid,a,b,v);
else if(a>mid) update(i<<1|1,mid+1,r,a,b,v);
else {
update(i<<1,l,mid,a,mid,v);
update(i<<1|1,mid+1,r,mid+1,b,v);
}
}
_LL query(int i,int l,int r,_LL p)
{
int mid;
if(l==r) return p*p*A[i]+p*B[i]+C[i];
mid=(l+r)/2;
A[i<<1]+=A[i];B[i<<1]+=B[i];C[i<<1]+=C[i];
A[i<<1|1]+=A[i];B[i<<1|1]+=B[i];C[i<<1|1]+=C[i];
A[i]=B[i]=C[i]=0;
if(p<=mid) return query(i<<1,l,mid,p);
else return query(i<<1|1,mid+1,r,p);
}
void POP(_LL a,_LL b,_LL x,_LL y)
{
int m=a<b?b:a,t=x>y?x:y,t2=x>y?y:x;
_LL v[3]={0,0,0};
v[2]=(x-a)*(y-b);
update(1,1,n,t+1,n,v);
v[0]=1;v[1]=-(a+b);v[2]=a*b;
if(t2>=m) update(1,1,n,m+1,t2,v);
if(y>x){
v[0]-=1;
v[1]+=x+b;v[2]-=x*b;
}
else if(x>y)
{
v[0]-=1;
v[1]+=a+y;v[2]-=a*y;
}
if(m>t2) t2=m;
update(1,1,n,t2+1,t,v);
}
int main()
{
int cas,m,i;
_LL x1,x2,y1,y2;
scanf("%d",&cas);
while(cas--)
{
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);
POP(x1,y1,x2,y2);
}
scanf("%d",&m);
while(m--)
{
scanf("%I64d",&x1);
printf("%I64d\n",query(1,1,n,x1));
}
}
return 0;
}
题目大意:
在第一象限中给出若干矩形(点范围1e5,矩形个数20000),现在给出一些询问(次数20000),每次询问给出一个整数t,问在(0,0)到(t,t)范围的矩形面积和。
解题思路:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; struct point{ long long x,y; friend bool operator < (const point &a,const point &b){ return max(a.x,a.y)<max(b.x,b.y); } }; point a[50001]; long long suma[50001],sumb[50001],suma_mul[50001],sumb_mul[50001]; point b[50001]; int find_a(int l,int r,long long t){ while(r>=l){ int m=(l+r)/2; if(t==max(a[m].x,a[m].y))return m; if(t<max(a[m].x,a[m].y))r=m-1; else l=m+1; } return l; } int find_b(int l,int r,long long t){ while(r>=l){ int m=(l+r)/2; if(t==max(b[m].x,b[m].y))return m; if(t<max(b[m].x,b[m].y))r=m-1; else l=m+1; } return l; } int main(){ int T; scanf("%d",&T); while(T--){ memset(suma,0,sizeof(suma)); memset(sumb,0,sizeof(sumb)); memset(suma_mul,0,sizeof(suma_mul)); memset(sumb_mul,0,sizeof(sumb_mul)); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); int n; scanf("%d",&n); for(int i=1;i<=n;i++){ long long x1,y1,x2,y2; scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2); //cin>>x1>>y1>>x2>>y2; a[2*i-1]=(point){x1,y1}; a[2*i]=(point){x2,y2}; b[2*i-1]=(point){x1,y2}; b[2*i]=(point){x2,y1}; } sort(a,a+2*n+1); sort(b,b+2*n+1); for(int i=1;i<=2*n;i++){ suma[i]=suma[i-1]+a[i].x+a[i].y; sumb[i]=sumb[i-1]+b[i].x+b[i].y; suma_mul[i]=suma_mul[i-1]+a[i].x*a[i].y; sumb_mul[i]=sumb_mul[i-1]+b[i].x*b[i].y; } suma[2*n+1]=suma[2*n]; sumb[2*n+1]=sumb[2*n]; suma_mul[2*n+1]=suma_mul[2*n]; sumb_mul[2*n+1]=sumb_mul[2*n]; int q; scanf("%d",&q); while(q--){ long long x; scanf("%I64d",&x); long long sum=0; int m=find_a(1,2*n,x); if(m>2*n)m=2*n; if(x<max(a[m].x,a[m].y))m--; sum=m*x*x-x*suma[m]+suma_mul[m]; m=find_b(1,2*n,x); if(m>2*n)m=2*n; if(x<max(b[m].x,b[m].y))m--; sum=sum-(m*x*x-x*sumb[m]+sumb_mul[m]); printf("%I64d\n",sum); //cout<<sum<<endl; } } }
- hdu 4533 威威猫系列故事——晒被子(两种方法)
- HDU 4533 威威猫系列故事——晒被子
- Hdu 4533 威威猫系列故事——晒被子
- hdu 4533 威威猫系列故事——晒被子
- hdu 4533 威威猫系列故事——晒被子
- hdu 4533 威威猫系列故事——晒被子(成段更新)
- hdu 4533 威威猫系列故事——晒被子(线段树 成端更新)
- HDU-4533:威威猫系列故事——晒被子(线段树延迟更新+推公式)
- 威威猫系列故事——晒被子
- HDOJ 4533 威威猫系列故事——晒被子
- hdu-4533-威威猫系列故事――晒被子----
- hdu 4533 威威猫系列故事――晒被子(二重等差数列+差分前缀和)
- hdu4533-威威猫系列故事——晒被子
- hdu4533 威威猫系列故事——晒被子
- HDU 4533 威威猫系列故事――晒被子 (线段树)
- hud 2013腾讯编程马拉松 威威猫系列故事——晒被子
- HDU 4533 威威猫系列故事――晒被子(线段树区间更新+分情况推公式)
- HDU4533 威威猫系列故事――晒被子
- 学会JAVA之前,再不做该死的数学题了
- QSlider自画样式
- JSON的结构
- 基于GMM的说话人识别模型(matlab)
- 基于Android应用开发的跨进程通信实现(IPC)
- hdu 4533 威威猫系列故事——晒被子(两种方法)
- hdu 4530 小Q系列故事——大笨钟
- django 中如何处理checkbox
- 一个MessageBox窗口[演示]ShellCode(WINXPSP2下测试通过)
- Jsp文件发布后中文乱码
- uva714 - Copying Books
- 将servlet中的list传递到JSP页面中去
- 关于thinkphp入库出现两次反斜线转义和thinkphp数据库类的转义
- 最大最小堆