zoukankan      html  css  js  c++  java
  • Luogu P1558 色板游戏【线段树/状态压缩】By cellur925

    题目传送门

    今天非常想再看一遍霸王别姬想不进去题于是开始刷数据结构

    注意到至多只有(30)种颜色,啊啊啊啊我一开始竟然想的不是状态压缩而是在线段树中存一个30大小的数组,这样每次更新的时候暴力循环一遍。hhhhh。

    可能这样比较好想吧,但是比正解状态压缩一下不知道差到哪里去了:)。开始还智障地把每次循环的次数开成30,那给出的色板数有什么用hh,这样是80分,改后AC。

    #include<cstdio>
    #include<algorithm>
    #define maxn 100090
    
    using namespace std;
    
    int n,Q,tot;
    char op[10];
    struct SegmentTree{
    	int l,r;int lazy;
    	int col[35];
    }t[maxn*4];
    
    void re(int &x)
    {
    	x=0;
    	char ch=getchar();
    	bool flag=false;
    	while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
    	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    	x=flag ? -x : x;
    }
    
    void build(int p,int l,int r)
    {
    	t[p].l=l,t[p].r=r;
    	if(l==r)
    	{
    		t[p].col[1]=1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	t[p].col[1]=t[p<<1].col[1]+t[p<<1|1].col[1];
    }
    
    void update(int p)
    {
    	if(!t[p].lazy||t[p].l==t[p].r) return ;
    	t[p<<1].lazy=t[p].lazy;t[p<<1|1].lazy=t[p].lazy;
    	for(int i=1;i<=tot;i++)
    		t[p<<1].col[i]=0,t[p<<1|1].col[i]=0;
    	t[p<<1].col[t[p].lazy]+=t[p<<1].r-t[p<<1].l+1;
    	t[p<<1|1].col[t[p].lazy]+=t[p<<1|1].r-t[p<<1|1].l+1;
    	t[p].lazy=0;
    }
    
    void change(int p,int l,int r,int id)
    {
    	update(p);
    	if(t[p].l==l&&t[p].r==r)
    	{
    		for(int i=1;i<=tot;i++)
    			t[p].col[i]=0;
    		t[p].col[id]+=r-l+1;
    		t[p].lazy=id;
    		return ;
    	}
    	int mid=(t[p].l+t[p].r)>>1;
    	if(l>mid) change(p<<1|1,l,r,id);
    	else if(r<=mid) change(p<<1,l,r,id);
    	else change(p<<1,l,mid,id),change(p<<1|1,mid+1,r,id);
    	for(int i=1;i<=tot;i++)
    		t[p].col[i]=t[p<<1].col[i]+t[p<<1|1].col[i];
    }
    
    int ask(int p,int l,int r,int id)
    {
    	update(p);
    	if(t[p].l==l&&t[p].r==r) return t[p].col[id];
    	int mid=(t[p].l+t[p].r)>>1;
    	if(l>mid) return ask(p<<1|1,l,r,id);
    	else if(r<=mid) return ask(p<<1,l,r,id);
    	else return ask(p<<1,l,mid,id)+ask(p<<1|1,mid+1,r,id);
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&tot,&Q);
    	build(1,1,n);	
    	while(Q--)
    	{
    		scanf("%s",op+1);
    		if(op[1]=='C')
    		{
    			int x=0,y=0,z=0;
    			scanf("%d%d%d",&x,&y,&z);
    			if(x>y) swap(x,y);
    			change(1,x,y,z);
    		}
    		else if(op[1]=='P')
    		{
    			int x=0,y=0;
    			scanf("%d%d",&x,&y);
    			if(x>y) swap(x,y);
    			int cnt=0;
    			for(int i=1;i<=tot;i++)
    				if(ask(1,x,y,i)>0) cnt++;
    			printf("%d
    ",cnt);
    		}
    	}
    	return 0;
    }
    

    最正确的做法是把每个节点的色板情况压成一个状态数,更新的时候用位运算更新==。这种方法我没有写,找了一个大佬写的:传送门

  • 相关阅读:
    简单理解桶排序
    实现js的类似alert效果的函数
    简单理解插入排序
    一个js简单的日历显示效果的函数
    详解一个自己原创的正则匹配IP的表达式
    一个简单的js实现倒计时函数
    简单理解冒泡排序
    简单理解js的this
    vue项目分享html页面(服务器只能内网访问)
    vue项目移动端查看、分享pdf(服务器只能内网访问)
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9901773.html
Copyright © 2011-2022 走看看