您的位置:首页 > 其它

F - Count the Colors

2016-03-24 16:16 393 查看
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66989#problem/F

线段树入门,起初,设置数组sum=-1表示无颜色,sum=-2表示下方无统一颜色;sum>=0表示颜色为sum的占据了整个子树

li ri数组==-1,-1表示左右无统一颜色其他表示区间rt左边颜色为li右边为ri,这样既可实现本题

看代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <string>
#define SI(T)int T;scanf("%d",&T)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
using namespace std;
const int SIZE=5;
const int maxn=1<<30;
int sum[SIZE<<2],li[SIZE<<2],ri[SIZE<<2];
int cnt[SIZE];
void pushup(int rt){
if(sum[rt<<1]!=-1||sum[rt<<1|1]!=-1){
li[rt]=ri[rt]=-1;
sum[rt]=-2;
return;
}
if(ri[rt<<1]==li[rt<<1|1]){
sum[rt]=li[rt]=ri[rt]=ri[rt<<1];
}
}
void pushdown(int rt){
if(sum[rt]>0){
sum[rt<<1]=sum[rt<<1|1]=sum[rt];
sum[rt]=-2;
}
}
void build(int l,int r,int rt){
memset(sum,-1,sizeof(sum));
memset(li,-1,sizeof(li));
memset(ri,-1,sizeof(ri));
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
sum[rt]=li[rt]=ri[rt]=c;
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m)update(L,R,c,lson);
if(R>m)update(L,R,c,rson);
pushup(rt);
}
void query(int l,int r,int rt){
if(sum[rt]>0){
cnt[sum[rt]]++;
return ;
}
if(sum[rt]==-1)return;
int m=(l+r)>>1;
if(l<=m)query(lson);
if(r>m)query(rson);
}
int main()
{
int n,x1,x2,c;
while(scanf("%d",&n)!=EOF){
memset(cnt,0,sizeof(cnt));
build(1,SIZE,1);
for(int i=0;i<n;i++){
scanf("%d%d%d",&x1,&x2,&c);
update(x1+1,x2,c,1,SIZE,1);
}
query(1,SIZE,1);
for(int i=0;i<SIZE<<1;i++)
printf("%d %d\n",sum[i],i);
for(int i=0;i<SIZE;i++){
if(cnt[i]){
printf("%d %d\n",i,cnt[i]);
}
}
}
return 0;
}
但是要是更新的是3跟4区间从二叉树上看3跟4区间分隔在了两颗子树,虽然他们在线上是链接的,但是在线段树上却是断开的,导致了错误。

吃个饭回来好像明白了些什么了,rili数组干嘛的。。。明显上面的代码没有用,然后根据后序遍历树个特点(神奇的地方)设置一个前驱temp,刚刚好解决了上面的问题,4的前驱刚好是3。代码贴上

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <string>
#define SI(T)int T;scanf("%d",&T)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
using namespace std;
const int SIZE=8080;
const int maxn=1<<30;
int sum[SIZE<<2];
int cnt[SIZE];
int temp;
void pushup(int rt){
if(sum[rt<<1]==-2||sum[rt<<1|1]==-2){
sum[rt]=-2;
return;
}
if(sum[rt<<1]==sum[rt<<1|1])sum[rt]=sum[rt<<1];
else sum[rt]=-2;
}
void pushdown(int rt){
if(sum[rt]>=0){
sum[rt<<1]=sum[rt<<1|1]=sum[rt];
sum[rt]=-2;
}
}
void build(int l,int r,int rt){
sum[rt]=-1;
if(l==r)return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
sum[rt]=c;
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m)update(L,R,c,lson);
if(R>m)update(L,R,c,rson);
pushup(rt);
}
void query(int l,int r,int rt){
if(sum[rt]>=0){
if(temp==sum[rt])return;
temp=sum[rt];
cnt[sum[rt]]++;
return ;
}
if(sum[rt]==-1){temp=-1;return;}
int m=(l+r)>>1;
if(l<=m)query(lson);
if(r>m)query(rson);
}
int main()
{
int n,x1,x2,c;
while(scanf("%d",&n)!=EOF){
memset(cnt,0,sizeof(cnt));
build(1,SIZE,1);
for(int i=0;i<n;i++){
scanf("%d%d%d",&x1,&x2,&c);
update(x1+1,x2,c,1,SIZE,1);
}
temp=-1;
query(1,SIZE,1);
for(int i=0;i<SIZE;i++){
if(cnt[i]){
printf("%d %d\n",i,cnt[i]);
}
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: