题解 P3219 【[HNOI2012]三角形覆盖问题】
题意
(很好理解吧qaq)
给一堆等腰三角形,求面积并
前言
这题最快有
其他dalao们的做法都是
由于数据水,我这个蒟蒻只会以下这种水法。。。
题解
从下往上扫描线(可一格一格地扫),当前要计算的面积就是一堆梯形,它会由斜边产生缺口(即上底比下底短)。可以把它们合起来算,记录 下底长之和 和 缺口大小(上下底的差) 即可更新答案。
扫到一个新的三角形,枚举其斜边整点,更新数据。(具体更新方法请见代码)
时间复杂度
我也不知道怎么过的,反正就是过了。。。
最慢(#10)143ms
代码
#include<bits/stdc++.h>
#define db double
#define ll long long
#define inf 1000009
#define eps 1e-11
#define INF 1e11
#define rd(n) {n=0;char ch;int f=0;do{ch=getchar();if(ch=='-'){f=1;}}while(ch<'0'||ch>'9');while('0'<=ch&&ch<='9'){n=(n<<1)+(n<<3)+ch-48;ch=getchar();}if(f)n=-n;}
using namespace std;
int n;
int x[inf],d[inf];
int s[inf],mx[inf];
/*s[i]表示第i行梯形上底与下地之差*/
/*mx[i]表示当前第i列的最高点y值*/
vector <int> pos[inf];
int main(){
rd(n)
int y,maxy=0;
for (int i=1;i<=n;i++){
rd(x[i]) rd(y) rd(d[i])
pos[y].push_back(i);
maxy=max(maxy,y+d[i]);
}
ll ans=0;
int now=0;//now是当前行下底长
for (int i=0;i<=maxy;i++){
ans+=(ll)(now*2-s[i]);
now-=s[i];
int cnt=pos[i].size();
for (int j=0;j<cnt;j++){
int id=pos[i][j];
for (int k=0;k<d[id];k++){
if (i+d[id]-k>mx[x[id]+k]){
if (mx[x[id]+k]<=i){
now++;
}
/*若当前列旧的最高点小于当前,而现在在此列增加了更高的三角形,下一行的梯形的下底会加大一格*/
s[mx[x[id]+k]]--;
/*旧的缺口被填上,在更高点产生新的缺口*/
mx[x[id]+k]=i+d[id]-k;
s[mx[x[id]+k]]++;
}
}
}
}
printf("%.1lf\n",(db)ans/2.0);
return 0;
}