【NOIP模拟】颜料大乱斗

来源:互联网 发布:unity3d 上海培训 编辑:程序博客网 时间:2024/03/29 09:37

Description

这里写图片描述

Solution

开始看到前面的题目那么水,到这题时就开始胡思乱想了,待修改莫队?树套树?30棵线段树?
然后我打了30棵线段树,常数十分的大啊!
超时30分TAT。
然后旁边的人把30个颜色的值放到同一个节点上,然后就对了,?????
常数小而已嘛!
虽然两个方法的时间复杂度理论上是一样的。
其实就是每个节点存储30个颜色是否出现过,然后两个儿子向上合并就好了。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;int i,j,k,l,n,m;int a,b,c,d,num;struct node{    int add;    int son[31];}t[100007*3],ans,p;char s[10];void down(int x,int l,int r){    if(l==r)return;    int mid=(l+r)/2;    if(t[x].add){        t[x*2].add=t[x].add,t[x*2+1].add=t[x].add;        int i;        fo(i,1,c)t[x*2].son[i]=t[x*2+1].son[i]=t[x].son[i];        t[x].add=0;    }}node merge(node x,node y){    int i;    node z;memset(z.son,0,sizeof(z.son));    fo(i,1,c)z.son[i]=x.son[i]|y.son[i];        return z;}void change(int x,int l,int r,int y,int z,int o){    down(x,l,r);    if(l==y&&r==z){        memset(t[x].son,0,sizeof(t[x].son));        t[x].son[o]=1;        t[x].add=o;        return;    }    int mid=(l+r)/2;    if(z<=mid)change(x*2,l,mid,y,z,o);    else if(y>mid)change(x*2+1,mid+1,r,y,z,o);    else{        change(x*2,l,mid,y,mid,o);        change(x*2+1,mid+1,r,mid+1,z,o);    }    int i;    fo(i,1,c)t[x].son[i]=t[x*2].son[i]|t[x*2+1].son[i];}node find(int x,int l,int r,int y,int z){    down(x,l,r);    if(l==y&&r==z){        int i,o=0;       return t[x];    }    int mid=(l+r)/2;    if(z<=mid)return find(x*2,l,mid,y,z);    else if(y>mid)return find(x*2+1,mid+1,r,y,z);    else{        node q;memset(q.son,0,sizeof(q.son));        q=merge(find(x*2,l,mid,y,mid),find(x*2+1,mid+1,r,mid+1,z));        return q;    }}int main(){//  freopen("fan.in","r",stdin);//  freopen("fan.out","w",stdout);    scanf("%d%d%d",&n,&c,&m);    change(1,1,n,1,n,1);    while(m--){        scanf("%s%d%d",s,&a,&b);        if(a>b)swap(a,b);        if(s[0]=='C'){            scanf("%d",&d);            change(1,1,n,a,b,d);        }        else{            if(a>b)swap(a,b);            ans=find(1,1,n,a,b);            int o=0;            fo(i,1,30)if(ans.son[i])o++;            printf("%d\n",o);        }    }}
1 0
原创粉丝点击