# Description

Luogu 传送门

# Solution

观察到 nn 极小,坐标的范围也不是特别大,我们考虑直接暴力求解!

不难发现,一个三角形覆盖的格子中分为两种情况:

  • 全部覆盖。

  • 覆盖了左下角,右上角没有被覆盖。

因此我们可以把一个格子拆成左下角和右上角两个小三角形来计算,然后总格子数会是一个整数,最后答案再除以 2 即可。

再来看这个小三角形如何统计。

我们考虑枚举每一列,然后开一个数组记录当前列被覆盖的情况。

不难发现由于三角形的摆放方式的特点,第 x+1x + 1 列与第 xx 列是有很多相似之处的,具体来说:

  • 如果一个三角形这两列都不包含自然无事发生

  • 如果一个输入的三角形同时包含了这两列,那么第 xx 列会比第 x+1x + 1 列多包含两个小三角形。

  • 如果第一个三角形包含 x+1x + 1 列,但不包含 xx 列,那么需要对这个数组进行清空。

是不是很简单?

这个复杂度为什么是对的呢?明明看上去是 O(nS2)O(nS^2) 的啊(外层枚举列,对于每一列枚举每个三角形,最内层是上述第三种情况的清空)

但事实上清空操作只会出现 nn 次,所以复杂度还是 O(nS)O(nS) 的。

# Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;
namespace IO{
    inline int read(){
        int x = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch)){if(ch == '-') f = -1; ch = getchar();}
        while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x * f;
    }
    template <typename T> inline void write(T x){
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
}
using namespace IO;
const int N = 4e6 + 10;
int n, mx;
struct node{
    int x, y, r, right;
}a[15];
bool b[N];
ll cnt, ans;
inline void update(int x) {cnt += (b[x] ? -1 : 1), b[x] ^= 1;}
int main(){
    n = read();
    for(int i = 1; i <= n; ++i){
        a[i] = (node){read(), read(), read()};
        a[i].right = a[i].y + a[i].r, mx = max(mx, a[i].right);//right 是三角形右下角的横坐标
    }
    for(int i = mx - 1; i >= 1; --i){// 枚举每一列
        for(int j = 1; j <= n; ++j){
            if(i >= a[j].y && i < a[j].right){// 当前列和右边一列都在这个三角形中
                int tmp = (a[j].right - i + a[j].x) << 1;// 手玩一下发现是多出来的一个小三角形
                update(tmp);
                if(i != a[j].right - 1) update(tmp - 1);// 同样手玩一下,是多出来的另一个小三角形,但是这个要特判一下,应该不难理解吧
            }
            if(i == a[j].y - 1){// 清空
                int tmp = a[j].right - (i + 1) + a[j].x;
                for(int k = (a[j].x + 1) << 1; k <= (tmp << 1); ++k) update(k);
            }
        }
        ans += cnt;
    }
    printf("%.1f\n", 1.0 * ans / 2);
    return 0;
}

# End