zoukankan      html  css  js  c++  java
  • 洛谷1558——色板游戏(线段树,位运算 )

    题目大意:
    给定一个长度为n的序列,每一个位置的初始颜色都是1,现在有m个操作。
    (C l r x)([l,r])的颜色都修改成x
    (P l r)查询[l,r]的颜色有多少种
    其中!
    颜色种类不超过30

    经过观察,我们发现这个题的颜色种类特别少!那么我们可以直接将线段树节点所对应的区间含的颜色压成一个二进制
    然后在合并的时候
    (f[root]=f[2*root] | f[2*root+1])
    就可以了
    再就是query的时候,同样也是求一个总的按位或的一个值
    直接求就行
    而修改操作就是将(f[root])直接改为((1<<p))
    顺便下方标记就可以
    上代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<vector>
    #define ll long long
    
    using namespace std;
    
    inline int read()
    {
       int x=0,f=1;char ch=getchar();
       while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
       while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
       return x*f;
    }
    
    const int maxn = 1e5+1e2;
    
    ll f[4*maxn],add[4*maxn];
    int n,m;
    
    int count(ll x)
    {
    	int cnt=0;
    	while (x)
    	{
    		if (x&1) cnt++;
    		x>>=1;
    	}
    	return cnt;
    }
    
    void up(int root)
    {
    	f[root]=(f[2*root]|f[2*root+1]);
    }
    
    void pushdown(int root,int l,int r)
    {
    	if (add[root])
    	{
    		add[2*root]=add[root];
    		add[2*root+1]=add[root];
    		f[2*root]=(1 << add[root]);
    		f[2*root+1]=(1 << add[root]);
    		add[root]=0;
    	}
    }
    
    void build(int root,int l,int r)
    {
    	if (l==r)
    	{
    		f[root]=2;
    		return;
    	}
    	int mid = (l+r) >> 1;
    	build(2*root,l,mid);
    	build(2*root+1,mid+1,r);
    	up(root);
    }
    void update(int root,int l,int r,int x,int y,ll p)
    {
    	if (x<=l && r<=y)
    	{
    		f[root]=(1 << p);
    		add[root]=p;
    		return;
    	}
    	pushdown(root,l,r);
    	int mid = (l+r) >> 1;
    	if (x<=mid) update(2*root,l,mid,x,y,p);
    	if (y>mid) update(2*root+1,mid+1,r,x,y,p);
    	up(root);
    }
    
    ll query(int root,int l,int r,int x,int y)
    {
    	if (x<=l && r<=y) 
    	  return f[root];
    	pushdown(root,l,r);
    	int mid = (l+r) >> 1;
    	ll ans=0;
    	if (x<=mid) ans=(ans | query(2*root,l,mid,x,y));
    	if (y>mid) ans=(ans | query(2*root+1,mid+1,r,x,y));
    	return ans;
    }
    
    int l;
    
    int main()
    {
      scanf("%d%d%d",&n,&l,&m);
      build(1,1,n);
      for (int i=1;i<=m;i++)
      {
      	  char s[10];
      	  scanf("%s",s+1);
      	  if (s[1]=='C')
      	  {
      	  	int x=read(),y=read();
      	  	if (x>y) swap(x,y);
    		ll z;
    		scanf("%lld",&z);
      	  	update(1,1,n,x,y,z);
    	  }
    	  if (s[1]=='P')
    	  {
    	  	int x=read(),y=read();
    	  	if (x>y) swap(x,y);
    	  	//cout<<query(1,1,n,x,y)<<endl;
    	  	printf("%d
    ",count(query(1,1,n,x,y)));
    	  }
    	  
      }
      return 0;
    }
    
    
  • 相关阅读:
    Zlib编译
    最新Webstrom, Idea 2019.2.3 的激活
    图像理解与深度学习开篇
    C# 反射(Reflection)
    SpringMVC中使用forward和redirect进行转发和重定向以及重定向时如何传参详解
    Navicat for Oracle中如何使用外键
    【数据库】主键,外键,主表,从表,关联表,父表,子表
    onclick事件没有反应的五种可能情况
    button小手设置 css的cursor
    Spring MVC F5刷新问题
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160726.html
Copyright © 2011-2022 走看看