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!

posted @ 2019-12-04 16:05  国土战略局特工  阅读(204)  评论(0)    收藏  举报