http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=216#problem/L
花了两个多小时才写完,结果一直RE。
我用1 2 4表示三原色,结构体里有两个信息:sta(1~7)表示这段区间的颜色状态,len[8]表示这段区间每种颜色的长度。后来想想这样处理不对,因为同一区间可能会被同一种颜色多次覆盖。但是我在sta中只记录了一次这样的颜色。
但是稍微一改就对了,不需要sta,拿一个数组cnt[3]表示0 1 2 这三种颜色出现了几次,然后再用三原色去合成其他颜色。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL __int64 #define eps 1e-12 #define PI acos(-1.0) #define PP pair<LL,LL> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 20010; const int mod = 1000000007; int x[maxn]; LL area[10]; struct Line { int x1,x2,y; int tag,col; bool operator < (const struct Line &tmp)const { return y < tmp.y; } }line[maxn]; struct node { int l,r; int cnt[4]; //该区间被三原色覆盖的次数 int len[10];//每种颜色的长度 }tree[maxn*4]; void build(int v, int l, int r) { tree[v].l = l; tree[v].r = r; for(int i = 1; i <= 7; i++) tree[v].len[i] = 0; for(int i = 0; i <= 2; i++) tree[v].cnt[i] = 0; if(l == r) return; int mid = (l+r)>>1; build(v*2,l,mid); build(v*2+1,mid+1,r); } int Binsearch(int l, int r, int key) { int mid,low = l,high = r; while(high >= low) { mid = (low + high)>>1; if(x[mid] == key) return mid; if(x[mid] > key) high = mid-1; else low = mid+1; } return -1; } //维护区间的长度 void maintain(int v) { int sta = 0; for(int i = 0; i <= 2; i++) { if(tree[v].cnt[i] > 0) sta += (1 << i); } if(sta) //该区间有一种颜色覆盖 { memset(tree[v].len,0,sizeof(tree[v].len)); //先把所有颜色初始化为0 tree[v].len[sta] = x[tree[v].r+1] - x[tree[v].l];//sta这种颜色的长度 if(tree[v].l == tree[v].r)//叶子节点 return; for(int i = 1; i <= 7; i++)//若子节点还有别的颜色, { if(sta != (sta|i) ) { int tmp = tree[v*2].len[i] + tree[v*2+1].len[i]; tree[v].len[sta|i] += tmp;//混合后的颜色长度增加 tree[v].len[sta] -= tmp;//原来的颜色减少 } } } else if(tree[v].l == tree[v].r) memset(tree[v].len,0,sizeof(tree[v].len)); else { for(int i = 1; i <= 7; i++) tree[v].len[i] = tree[v*2].len[i] + tree[v*2+1].len[i]; } return; } void update(int v, int l, int r, int col, int tag) { if(tree[v].l == l && tree[v].r == r) { tree[v].cnt[col] += tag; maintain(v); return; } int mid = (tree[v].l + tree[v].r)>>1; if(r <= mid) update(v*2,l,r,col,tag); else if(l > mid) update(v*2+1,l,r,col,tag); else { update(v*2,l,mid,col,tag); update(v*2+1,mid+1,r,col,tag); } maintain(v); } int main() { int test; int n,k,x1,x2,y1,y2,t1; char ch[3]; scanf("%d",&test); for(int item = 1; item <= test; item++) { memset(area,0,sizeof(area)); scanf("%d",&n); t1 = 0; for(int i = 1; i <= n; i++) { scanf("%s %d %d %d %d",ch,&x1,&y1,&x2,&y2); struct Line tmp; if(ch[0] == 'R') tmp.col = 0; else if(ch[0] == 'G') tmp.col = 1; else tmp.col = 2; tmp.x1 = x1; tmp.x2 = x2; tmp.y = y1; tmp.tag = 1; line[++t1] = tmp; x[t1] = x1; tmp.y = y2; tmp.tag = -1; line[++t1] = tmp; x[t1] = x2; } sort(line+1,line+1+t1); sort(x+1,x+1+t1); k = 1; for(int i = 2; i <= t1; i++) { if(x[i] != x[i-1]) x[++k] = x[i]; } build(1,1,k); for(int i = 1; i < t1; i++) { int l = Binsearch(1,k,line[i].x1); int r = Binsearch(1,k,line[i].x2)-1; update(1,l,r,line[i].col,line[i].tag); for(int j = 1; j <= 7; j++) area[j] += (LL)tree[1].len[j] * (LL)(line[i+1].y - line[i].y); } printf("Case %d:\n",item); for(int i = 1; i <= 2; i++) printf("%I64d\n",area[i]); printf("%I64d\n%I64d\n",area[4],area[3]); for(int i = 5; i <= 7; i++) printf("%I64d\n",area[i]); } return 0; }