线段树扫描线 求矩阵的覆盖面积与周长
题意:给出几个矩阵求这些矩阵覆盖的面积:
给出左上角与右下角
Sample Input
2
0 5 4 1
2 4 6 2
Sample Output
20
#include<bits/stdc++.h> using namespace std; #define LL long long #define lson l, m, rt<<1 #define rson m+1,r,rt<<1|1 const int maxn = 5e3 + 10; const int Base = 1e8; LL sum[maxn<<2]; int add[maxn]; int x[maxn<<2]; struct Node{ int flag; int l, r, h; Node(){}; Node(int L, int R, int H, int F):l(L),r(R),h(H),flag(F){}; bool operator < (const Node & rhs) const{ return this->h < rhs.h; }; }s[maxn]; void UPDOWN(int rt, int l, int r) { if(add[rt]) sum[rt] = x[r+1] - x[l]; else if(l == r) sum[rt] = 0; else sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void UPDATE(int L, int R, int c, int l, int r, int rt) { int m; if(L <= l && r <= R){ add[rt] += c; UPDOWN(rt, l, r); return ; } m = (l+r)>>1; if(L <= m) UPDATE(L, R, c, lson); if(R > m) UPDATE(L, R, c, rson); UPDOWN(rt, l, r); } int main(void) { int n; scanf("%d", &n); int x1, x2, y1, y2; int num = 0; for(int i=0; i<n; i++){ scanf("%d %d %d %d", &x1, &y1, &x2, &y2); x1 += Base, x2 += Base, y1 += Base, y2 += Base; x[num] = x1; s[num++] = Node(x1, x2, y1, 1); x[num] = x2; s[num++] = Node(x1, x2, y2, -1); } sort(x, x+num); sort(s, s+num); int idx = std::unique(x, x+num) - x; int L, R; long long ans = 0; for(int i=0; i<num-1; i++){ L = lower_bound(x, x+idx, s[i].l) - x; R = lower_bound(x, x+idx, s[i].r) - x - 1; UPDATE(L,R,s[i].flag,0,idx-1,1); ans+=(sum[1]*(1LL*s[i+1].h-1LL*s[i].h)); } printf("%lld\n", ans); return 0; }
给出左上角与右下角求矩阵的周长
#include<string.h> #include<stdio.h> #include<bits/stdc++.h> #include<algorithm> #define lson l, m, rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 5010; const int MAX = 10010; int add[2*MAX*4]; int sum[2*MAX*4]; struct Node{ int flag; int l, r, h; Node(){}; Node(int L, int R, int H):l(L),r(R),h(H){}; bool operator < (const Node &rhs) const{ if(this->h==rhs.h) return this->flag > rhs.flag; else return this->h < rhs.h; }; }sx[maxn<<1],sy[maxn<<1]; inline void Build(int l, int r, int rt) { add[rt] = sum[rt] = 0; if(l >= r) return ; int m = l+((r-l)>>1); Build(lson); Build(rson); } inline void pushup(int rt, int l, int r) { if(add[rt] > 0) sum[rt] = r - l + 1; else if(l==r) sum[rt] = 0; else sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } inline void update(int L, int R, int c, int l, int r, int rt) { int m; if(L <= l && r <= R){ add[rt] += c; pushup(rt, l, r); return ; } m = l + ((r-l)>>1); if(L <= m) update(L, R, c, lson); if(R > m) update(L, R, c, rson); pushup(rt, l, r); } int Solve(int minx, int maxx, int miny, int maxy, int num) { int ret = 0; int pre = 0; Build(minx, maxx-1, 1); for(int i=0; i<num; i++){ update(sx[i].l, sx[i].r-1, sx[i].flag, minx, maxx-1, 1); ret += abs(sum[1] - pre); pre = sum[1]; } //printf("%d\n", ret); Build(miny, maxy-1, 1); pre = 0; for(int i=0; i<num; i++){ update(sy[i].l, sy[i].r-1, sy[i].flag, miny, maxy-1, 1); ret += abs(sum[1] - pre); pre = sum[1]; } return ret; } int main(void) { //freopen("data1.in", "w", stdin); int n; while(~scanf("%d", &n)){ int maxx, maxy, minx, miny; maxx = maxy = -0x3f3f3f3f; minx = miny = 0x3f3f3f3f; int x1, y1, x2, y2; int num = 0; for(int i=0; i<n; i++){ scanf("%d %d %d %d", &x1,&y1,&x2,&y2); miny = min(y1, miny); minx = min(x1, minx); maxy = max(y2, maxy); maxx = max(x2, maxx); sx[num].l = x1, sx[num].r = x2, sx[num].h = y1, sx[num].flag = 1; sx[num+1].l=x1, sx[num+1].r=x2, sx[num+1].h=y2, sx[num+1].flag=-1; sy[num].l = y1, sy[num].r = y2, sy[num].h = x1, sy[num].flag = 1; sy[num+1].l=y1, sy[num+1].r=y2, sy[num+1].h=x2, sy[num+1].flag=-1; num+=2; } sort(sx, sx+num); sort(sy, sy+num); printf("%d\n", Solve(minx, maxx, miny, maxy, num)); } return 0; }
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 1010 #define lch(i) ((i)<<1) #define rch(i) ((i)<<1|1) double pos[2*N]; struct segment { double l,r,h; int v; }s[2*N]; struct node { int l,r,cnt; double s,ss; int mid() { return (l+r)>>1; } }t[2*N*4]; int n; int cmp(struct segment p ,struct segment q) { return p.h<q.h; } void build(int l ,int r ,int rt) { t[rt].l=l; t[rt].r=r; t[rt].cnt=t[rt].s=t[rt].ss=0; if(l==r) return ; int mid=t[rt].mid(); build(l,mid,lch(rt)); build(mid+1,r,rch(rt)); } int binarysearch(double key ,int low ,int high) { while(low <= high) { int mid=(low+high)>>1; if(pos[mid] == key) return mid; else if(pos[mid] < key) low=mid+1; else high=mid-1; } return -1; } void cal(int rt) { if(t[rt].cnt) t[rt].s = pos[t[rt].r+1] - pos[t[rt].l]; else if(t[rt].l == t[rt].r) t[rt].s=0; else t[rt].s = t[lch(rt)].s + t[rch(rt)].s; /**************************************************/ if(t[rt].cnt > 1) t[rt].ss = pos[t[rt].r+1] - pos[t[rt].l]; else if(t[rt].l == t[rt].r) t[rt].ss = 0; else if(t[rt].cnt == 1) t[rt].ss = t[lch(rt)].s + t[rch(rt)].s; else t[rt].ss = t[lch(rt)].ss + t[rch(rt)].ss; } void updata(int l , int r ,int v ,int rt) { if(t[rt].l==l && t[rt].r==r) { t[rt].cnt += v; cal(rt); return ; } int mid=t[rt].mid(); if(r<=mid) updata(l,r,v,lch(rt)); else if(l>mid) updata(l,r,v,rch(rt)); else { updata(l,mid,v,lch(rt)); updata(mid+1,r,v,rch(rt)); } cal(rt); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); int i,k; for(i=0,k=0; i<n; i++,k+=2) { double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); pos[k]=x1; pos[k+1]=x2; s[k].l=x1; s[k].r=x2; s[k].h=y1; s[k].v=1; s[k+1].l=x1; s[k+1].r=x2; s[k+1].h=y2; s[k+1].v=-1; } sort(pos,pos+k); sort(s,s+k,cmp); int m=1; for(i=1; i<k; i++) if(pos[i]!=pos[i-1]) pos[m++]=pos[i]; build(0,m-1,1); double res=0; for(i=0; i<k-1; i++) { int l=binarysearch(s[i].l,0,m-1); int r=binarysearch(s[i].r,0,m-1)-1; updata(l,r,s[i].v,1); res += t[1].ss*(s[i+1].h - s[i].h); } printf("%.2lf\n",res); } return 0; }