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;
    }
    
    
  • 相关阅读:
    hdu acm 2844 Coins 解题报告
    hdu 1963 Investment 解题报告
    codeforces 454B. Little Pony and Sort by Shift 解题报告
    广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
    hdu acm 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    hdu acm 1114 Piggy-Bank 解题报告
    poj 2531 Network Saboteur 解题报告
    数据库范式
    ngnix 配置CI框架 与 CI的简单使用
    Vundle的安装
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160726.html
Copyright © 2011-2022 走看看