自己的思路:题目给了三种颜色 R G B,能够组成7种颜色,我想到用状态压缩(R =1,G=2,B=4),因为他的颜色是由他的种类数决定的,所以我用异或来表示他的覆盖情况(这是我***的地方,我没理解基础的 +1,-1 为什么),后面debug发现我的覆盖情况出现的负值的情况,然后就没有思路了。
大佬博客:https://blog.csdn.net/ACM_cxlove/article/details/8015043
大佬思路:大佬用一个数组记录每个颜色出现的情况,其实就是+1,-1的情况(颜色出现到消失),还有一个我没想到的地方,就是更新长度的时候,如果这个区间被全部覆盖,当用儿子来更新父亲的时候,原本的颜色会减少,新的颜色会变多。
我是真的菜!Orz。。。
代码:
///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const int MAXN=1e5;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
struct node
{
ll l;
ll r;
ll h;
ll status;
bool friend operator<(node a,node b)
{
return a.h<b.h;
}
}line[20005];
ll x[20005];
struct xx
{
ll s[5];
ll sum[8];
}root[80005];
int judge(char x)
{
if(x=='R')
return 1;
if(x=='G')
return 2;
return 4;
}
void pushup(int sign,int l,int r)
{
int s=(root[sign].s[1]>0?1:0)|(root[sign].s[2]>0?2:0)|(root[sign].s[4]>0?4:0);
if(s) ///区间被全部覆盖
{
memset(root[sign].sum,0,sizeof(root[sign].sum));
root[sign].sum[s]=x[r+1]-x[l]; ///区间长度
for(int i=1;i<=7;i++)
{
if(s!=(s|i)) ///如果原来有其他颜色
{
ll add=root[sign<<1].sum[i]+root[sign<<1|1].sum[i];
root[sign].sum[s|i]+=add; ///混合的颜色增多
root[sign].sum[s]-=add; ///原本的颜色减少
}
}
}
else if(l==r) ///叶子节点
memset(root[sign].sum,0,sizeof(root[sign].sum));
else ///区间没有被完全覆盖,由儿子更新父亲
{
for(int i=0;i<=7;i++)
root[sign].sum[i]=root[sign<<1].sum[i]+root[sign<<1|1].sum[i];
}
}
void updateroot(int sign,int l,int r,int a,int b,int f)
{
if(l==a&&r==b) ///更新覆盖情况
{
if(f>0)
root[sign].s[f]++;
else
root[sign].s[-f]--;
pushup(sign,l,r);
return ;
}
int mid=(l+r)>>1;
if(b<=mid)
updateroot(sign<<1,l,mid,a,b,f);
else if(a>mid)
updateroot(sign<<1|1,mid+1,r,a,b,f);
else
{
updateroot(sign<<1,l,mid,a,mid,f);
updateroot(sign<<1|1,mid+1,r,mid+1,b,f);
}
pushup(sign,l,r);
}
int main()
{
ll t,n;
ll x1,y1,x2,y2;
char a[5];
scanf("%lld",&t);
for(int u=1;u<=t;u++)
{
memset(root,0,sizeof(root));
int sign=0;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%s %lld %lld %lld %lld",a,&x1,&y1,&x2,&y2);
ll p=judge(a[0]); ///判断颜色
line[++sign]=node{x1,x2,y1,p};
x[sign]=x1;
line[++sign]=node{x1,x2,y2,-p};
x[sign]=x2;
}
sort(line+1,line+1+sign);
sort(x+1,x+1+sign);
int d=unique(x+1,x+1+sign)-(x+1);
ll ans[10]={0};
for(int i=1;i<sign;i++)
{
int b=lower_bound(x+1,x+1+d,line[i].l)-x;
int c=lower_bound(x+1,x+1+d,line[i].r)-x-1;
updateroot(1,1,d-1,b,c,line[i].status);
if(line[i+1].h!=line[i].h)
{
for(int j=1;j<=7;j++)
ans[j]+=root[1].sum[j]*(line[i+1].h-line[i].h);
}
}
printf("Case %d:\n",u);
swap(ans[4],ans[3]);///因为输出顺序是1 2 4 3 5 6 7,换一下顺序方便输出
for(int i=1;i<=7;i++)
printf("%lld\n",ans[i]);
}
return 0;
}