NKOJ P2300 何老板搬砖

NKOJ P2300 何老板搬砖

再不改线段树格式我倒立女装


KONO题面哒!

暑假到了,你去给何老板打工,何老板问你会什么,你说只会搬砖。
  于是,何老板想检验一下你搬砖的实力:
  何老板有n块白色的方砖(编号1到n),他叫你把这n块按编号摆成了一条直线。
  你以为摆成直线就完事了吗?何老板是个很古怪的人,他还不停的向你发号司令,他的命令有下列三种:
  一.把第a到第b块砖换成颜色为c的砖。
  二.把第a到第b块砖中颜色为c的砖换成颜色为d的砖。
  三.回答第a到第b块砖中有哪几种不同的颜色。
  
  你要快速给出每次提问的正确答案,不然你就得不到这份工作了!
  (何老板的砖最多有7种不同的颜色,编号1到7,白色编号为1)。

数据范围:
$ n\leq 200000,m\leq 100000$


十次线段树爆炸十一次都是因为Pushdown的左右区间赋错值,我整个人都裂开

第一眼看到颜色只有7个就知道是状压。但是我想了半天没有想出来状压怎么写,于是搞了个暴力做法。开7棵线段树,记录每个颜色在当前区间内有多少个砖头。
每个1号操作擦除其余六棵树上的所有值,当前树把区间内砖头设为区间长度。
每个2号操作找到\(C\)树上目标区间内存在砖头的区间,把这些区间擦掉,再把\(D\)树上的这些区间设为区间长度。
每个3号操作就统计每棵树目标区间内存不存在值。
很暴力,但做了一点微小的优化后跑的飞飞飞飞快。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#define tp(p) if((p<<1|1)<=1200010)
using namespace std;
char *p1,*p2,buf[1<<20];
#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
//#define GC getchar()
inline int in()
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)){
        w|=ch=='-';
        ch=GC;
    }
    while(isdigit(ch)){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=GC;
    }
    return w?-x:x;
}
int n,m;
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
const int maxn=300010;
struct tree{
    int sum[4*maxn],tag[4*maxn];
    void pushup(int p){
        sum[p]=sum[ls(p)]+sum[rs(p)];
    }
    void pushdown(int p,int l,int r){
        int mid=((l+r)>>1);
        if(tag[p]==1){
            sum[ls(p)]=mid-l+1;
            sum[rs(p)]=r-mid;
            tag[ls(p)]=tag[rs(p)]=1;
        }
        else if(tag[p]==-1){
            sum[ls(p)]=sum[rs(p)]=0;
            tag[rs(p)]=tag[ls(p)]=-1;
        }
        tag[p]=0;
    }
    void ins(int l,int r,int p,int l1,int r1,int k)
    {
        pushdown(p,l1,r1);
        if(l<=l1&&r>=r1){
            if(k==1){
                sum[p]=r1-l1+1;
                tag[p]=1;
            }
            else{
                sum[p]=0;
                tag[p]=-1;
            }
            return;
        }
        int mid=((l1+r1)>>1);
        if(mid>=l)ins(l,r,ls(p),l1,mid,k);
        if(mid<r)ins(l,r,rs(p),mid+1,r1,k);
        pushup(p);
        return;
    }
    bool gs(int l,int r,int p,int l1,int r1)
    {
        pushdown(p,l1,r1);
        if(l<=l1&&r>=r1){
            return sum[p];
        }
        int mid=((l1+r1)>>1);
        bool res=0;
        if(mid>=l)res=(res|gs(l,r,ls(p),l1,mid));
        if(mid<r)res=(res|gs(l,r,rs(p),mid+1,r1));
        return res;
    }
}tr[8];
void change(int l,int r,int p,int l1,int r1,int c,int d)
{
    tr[c].pushdown(p,l1,r1);
    tr[d].pushdown(p,l1,r1);
    if(tr[c].sum[p]==0)return;
    
    if(l<=l1&&r>=r1&&tr[c].sum[p]==r1-l1+1){
        tr[c].sum[p]=0;
        tr[c].tag[p]=-1;
        tr[d].sum[p]=r1-l1+1;
        tr[d].tag[p]=1;
        return;
    }
    if(l1==r1)return;
    int mid=((l1+r1)>>1);
    if(mid>=l)change(l,r,ls(p),l1,mid,c,d);
    if(mid<r)change(l,r,rs(p),mid+1,r1,c,d);
    tr[c].pushup(p);
    tr[d].pushup(p);
    return;
}
int main()
{
    int i,j;
    n=in();m=in();
    tr[1].ins(1,n,1,1,n,1);
    for(i=1;i<=m;i++){
        int ch,a,b,c;
        ch=in();a=in();b=in();
        switch(ch){
            case 1:{
                c=in();
                for(j=1;j<=7;j++){
                    if(j==c)continue;
                    tr[j].ins(a,b,1,1,n,0);
                }
                tr[c].ins(a,b,1,1,n,1);
                break;
            }
            case 2:{
                int d;
                c=in();d=in();
                change(a,b,1,1,n,c,d);
                break;
            }
            case 3:{
                for(j=1;j<=7;j++)
                {
                    if(tr[j].gs(a,b,1,1,n)){
                        printf("%d ",j);
                    }
                }
                printf("\n");
                break;
            }
        }
    }
    return 0;
}

接下来是神佬zmr的状压做法

#include<stdio.h>
#include<bits/stdc++.h>
#define cut(l,r) ((l+r)>>1)
#define lson(i) (i<<1)
#define rson(i) ((i<<1)|1)
#define ll long long
#define intinf 1000000000
#define llinf 1000000000000000000LL
#define reint register int
#define st first
#define nd second
using namespace std;

char *p1,*p2,buf[1<<20];
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
//#define GC getchar()
inline int rd()
{
    int w=0,x=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=GC;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=GC;}
    return w?-x:x;
}
char pbuf[1<<20],*pp=pbuf;
void push(const char c){
    if(pp-pbuf==(1<<20)) fwrite(pbuf,1,(1<<20),stdout),pp=pbuf;
    *pp++=c;
}
inline void wt(int x){
    static int sta[35];int top=0;
    do{sta[top++]=x%10,x/=10;}while(x);
    while(top) push(sta[--top]+'0');
}
#define pn push('\n')
#define pk push(' ')

const int maxn=2e5+110;
const int maxr=maxn*4;
int n,m,a,b,c,d,id;
typedef pair<bool,pair<short,short> > arr;
struct node{
    int l,r;
    short sum;
    vector<arr>to_do;
}tree[maxn*4];

inline void push_up(int i)
{
    tree[i].sum=(tree[lson(i)].sum|tree[rson(i)].sum);
}

inline void push_down(int i)
{
    //标记为1表示换成颜色为change的砖
    //标记为2表示将change_from颜色的砖转换成颜色为change_to的砖
    if(!tree[i].to_do.size())return;
    arr tmp,t;
    int ls=lson(i),rs=rson(i);
    short fr,to;
    vector<arr>::iterator it;
    for(it=tree[i].to_do.begin();it!=tree[i].to_do.end();it++)
    {
        tmp=*it;fr=tmp.nd.st;to=tmp.nd.nd;
        if(tmp.st==false)
        {
            while(tree[ls].to_do.size()) tree[ls].to_do.erase(tree[ls].to_do.begin());
            while(tree[rs].to_do.size()) tree[rs].to_do.erase(tree[rs].to_do.begin());
            tree[ls].sum=(1<<(fr-1));
            tree[rs].sum=(1<<(fr-1));
            t.st=false;t.nd.st=fr;
            tree[ls].to_do.push_back(t);
            tree[rs].to_do.push_back(t);
        }
        else
        {
            t.st=true;t.nd.st=fr;t.nd.nd=to;
            if(tree[ls].sum&(1<<(fr-1)))
            {
                tree[ls].sum=(tree[ls].sum^(1<<fr-1));
                tree[ls].sum=(tree[ls].sum|(1<<(to-1)));
                tree[ls].to_do.push_back(t);
            }
            if(tree[rs].sum&(1<<(fr-1)))
            {
                tree[rs].sum=(tree[rs].sum^(1<<fr-1));
                tree[rs].sum=(tree[rs].sum|(1<<(to-1)));
                tree[rs].to_do.push_back(t);
            }
        }
    }
    while(tree[i].to_do.size()) tree[i].to_do.erase(tree[i].to_do.begin());
}

inline void build(int i,int l,int r)
{
    tree[i].l=l;tree[i].r=r;tree[i].sum=1;
    if(l==r) return;
    int mid=cut(tree[i].l,tree[i].r);
    build(lson(i),l,mid);
    build(rson(i),mid+1,r);
    push_up(i);
}

inline void change1(int i,int l,int r,int col)
{
    if(tree[i].l>=l&&tree[i].r<=r)
    {
        while(tree[i].to_do.size()) tree[i].to_do.erase(tree[i].to_do.begin());
        arr tmp;tmp.st=false;tmp.nd.st=col;
        tree[i].to_do.push_back(tmp);
        tree[i].sum=(1<<(col-1));
        return;
    }
    push_down(i);
    int mid=cut(tree[i].l,tree[i].r);
    if(mid>=l) change1(lson(i),l,r,col);
    if(mid<r) change1(rson(i),l,r,col);
    push_up(i);
}

inline void change2(int i,int l,int r,int fr,int to)
{
    if(tree[i].l>=l&&tree[i].r<=r)
    {
        arr tmp;tmp.st=true;tmp.nd.st=fr;tmp.nd.nd=to;
        if(tree[i].sum&(1<<(fr-1)))
        {
            tree[i].sum-=(1<<(fr-1));
            tree[i].sum=(tree[i].sum|(1<<(to-1)));
            tree[i].to_do.push_back(tmp);
        }
        return;
    }
    push_down(i);
    int mid=cut(tree[i].l,tree[i].r);
    if(mid>=l) change2(lson(i),l,r,fr,to);
    if(mid<r) change2(rson(i),l,r,fr,to);
    push_up(i);
}

inline int getans(int i,int l,int r)
{
    if(tree[i].l>=l&&tree[i].r<=r)
      return tree[i].sum;
    push_down(i);
    int mid=cut(tree[i].l,tree[i].r);short res=0;
    if(mid>=l) res=(res|getans(lson(i),l,r));
    if(mid<r) res=(res|getans(rson(i),l,r));
    return res;
}

int main()
{
    n=rd();m=rd();
    build(1,1,n);
    for(reint i=1;i<=m;i++)
    {
        id=rd();
        if(id==1)
        {
            a=rd();b=rd();c=rd();
            change1(1,a,b,c);
        }
        else if(id==2)
        {
            a=rd();b=rd();c=rd();d=rd();
            change2(1,a,b,c,d);
        }
        else
        {
            a=rd();b=rd();
            int ans=getans(1,a,b);
            for(short j=1;j<=7;j++)
              if(ans&(1<<(j-1))) push(j+'0'),pk;
            pn;
        }
    }
    fwrite(pbuf,1,pp-pbuf,stdout);
    return 0;
}

C96改造wsl!

猜你喜欢

转载自www.cnblogs.com/cooper233/p/11983491.html