【JZOJ 4603】颜料大乱斗

来源:互联网 发布:达内软件测试 编辑:程序博客网 时间:2024/05/11 09:04

Description

这里写图片描述
这里写图片描述
**强烈吐槽坑人

辣鸡题目

区间可能左端点>右端点,白色的颜色用1表示!!!**
表示被坑啦!!!100分没啦!!!

辣鸡出题人,颓我比赛,毁我人生!!!

Analysis

显然,可以用开30颗线段树来卡一卡。结果我就900ms+强行碾过了。

Code

#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int N=100005;int n,c,ans,lz[N*4];bool tr[32][N*4],bz[32];void build(int v,int l,int r){    if(l==r)    {        tr[1][v]=1;        return;    }    int mid=(l+r)>>1;    build(v+v,l,mid),build(v+v+1,mid+1,r);    tr[1][v]=1;}void update(int v,int z){    fo(i,1,30) tr[i][v]=0;    tr[z][v]=1;    lz[v]=z;}void down(int v){    if(!lz[v]) return;    update(v+v,lz[v]);    update(v+v+1,lz[v]);    lz[v]=0;}void change(int v,int l,int r,int x,int y,int z){    if(l==x && r==y)    {        update(v,z);        return;    }    down(v);    int mid=(l+r)>>1;    if(y<=mid) change(v+v,l,mid,x,y,z);    else    if(x>mid) change(v+v+1,mid+1,r,x,y,z);    else    change(v+v,l,mid,x,mid,z),change(v+v+1,mid+1,r,mid+1,y,z);    fo(i,1,30) tr[i][v]=tr[i][v+v] || tr[i][v+v+1];}void query(int v,int l,int r,int x,int y){    if(l==x && r==y)    {        fo(i,1,30)            if(!bz[i] && tr[i][v]) ans++,bz[i]=1;        return;    }    down(v);    int mid=(l+r)>>1;    if(y<=mid) query(v+v,l,mid,x,y);    else    if(x>mid) query(v+v+1,mid+1,r,x,y);    else    query(v+v,l,mid,x,mid),query(v+v+1,mid+1,r,mid+1,y);}int main(){    char ch;    int _,x,y,z;    scanf("%d %d %d\n",&n,&c,&_);    build(1,1,n);    while(_--)    {        scanf("%c %d %d",&ch,&x,&y);        if(x>y) swap(x,y);        if(ch=='C')        {            scanf("%d\n",&z);            change(1,1,n,x,y,z);        }        else        {            scanf("\n");            ans=0;            memset(bz,0,sizeof(bz));            query(1,1,n,x,y);            printf("%d\n",ans);        }    }    return 0;}
0 0