zoukankan      html  css  js  c++  java
  • 题解 CF121E Lucky Array

    这是一道线段树的好题。

    这个题的翻译有一点没翻译出来,就是无论怎么加序列中的数不会超过(10^4)

    那么在这个数据范围内可以发现由(4)(7)组成的数只有(30)

    所以我们可以打一个小小的表。

    为了防抄袭我的表打的是(2,3)组成的数。

    可以看到我的表最后插入了一个极大值,这个原因请自行思考,不再赘述。

    有了这个表之后我们可以维护每个数与最小的比它大的由(4)(7)组成的数的差,每次区间加用线段树维护,把差值减去(d)

    线段树维护一下这个区间的最小值以及最小值出现的次数,每次询问我们看如果最小值是(0)的话就直接返回最小值出现的次数即可,因为它一定是由(4)(7)组成的。

    当差值减小到比(0)还小的时候,我们就要对(x)维护下一个小于(x)且里(x)最近的(4,7) 组成的数的差值。这个维护的时候暴力维护,重新建树,每个数最多被修改(31)次,所以不会超时。

    复杂度(O(31mlog n))

    代码

    #include<bits/stdc++.h>
    #define eps 1e-7
    #define re register
    #define N 2001001
    #define MAX 2011
    #define PI 3.1415927
    #define inf 1e18
    using namespace std;
    typedef long long ll;
    typedef double db;
    const ll mod=1000000007;
    inline void read(re ll &ret)
    {
        ret=0;re ll pd=0;re char c=getchar();
        while(!isdigit(c)){pd|=c=='-';c=getchar();}
        while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c^48);c=getchar();}
        ret=pd?-ret:ret;
    }
    ll n,m,a[N],b[N],x,y,tmp;
    struct node
    {
    	ll l,r,mid,val,minn,sum;
    }seg[N];
    ll num[32]={0,2,3,22,23,32,33,222,223,232,233,322,323,332,333,2222,2223,2232,2233,2322,2323,2332,2333,3222,3223,3232,3233,3322,3323,3332,3333,200001}; 
    char s[N];
    inline void pushup(re ll pos)
    {
    	seg[pos].minn=min(seg[pos<<1].minn,seg[pos<<1|1].minn);
    	if(seg[pos].minn==seg[pos<<1].minn&&seg[pos].minn==seg[pos<<1|1].minn)
    		seg[pos].val=seg[pos<<1].val+seg[pos<<1|1].val;
    	else if(seg[pos].minn==seg[pos<<1].minn)
    		seg[pos].val=seg[pos<<1].val;
    	else
    		seg[pos].val=seg[pos<<1|1].val;
    	return;
    }
    inline void build(re ll pos,re ll l,re ll r)
    {
    	seg[pos].l=l;
    	seg[pos].r=r;
    	seg[pos].mid=l+r>>1;
    	if(l==r)
    	{
    		seg[pos].val=1;
    		for(re int i=1;i<=31;i++)
    		{
    			seg[pos].minn=num[i]-a[l];
    			b[l]=i;
    			if(num[i]>=a[l])
    				break;
    		}
    	}
    	else
    	{
    		build(pos<<1,l,seg[pos].mid);
    		build(pos<<1|1,seg[pos].mid+1,r);
    		pushup(pos);
    	}
    	return;
    }
    inline void rebuild(re ll pos)
    {
    	if(seg[pos].minn>=0)
    		return;
    	if(seg[pos].l==seg[pos].r)
    	{
    		a[seg[pos].l]=num[b[seg[pos].l]]-seg[pos].minn;
    		for(re int i=1;i<=31;i++)
    		{
    			seg[pos].minn=num[i]-a[seg[pos].l];
    			b[seg[pos].l]=i;
    			if(num[i]>=a[seg[pos].l])
    				break;
    		}
    	}
    	else
    	{
    		seg[pos<<1].minn-=seg[pos].sum;
    		seg[pos<<1].sum+=seg[pos].sum;
    		seg[pos<<1|1].minn-=seg[pos].sum;
    		seg[pos<<1|1].sum+=seg[pos].sum;
    		seg[pos].sum=0;
    		rebuild(pos<<1);
    		rebuild(pos<<1|1);
    		pushup(pos);
    	}
    }
    inline void add(re ll pos,re ll num)
    {
    	seg[pos].sum+=num;
    	seg[pos].minn-=num;
    	if(seg[pos].minn<0)
    		rebuild(pos);
    	return;
    }
    inline void pushdown(re ll pos)
    {
    	add(pos<<1,seg[pos].sum);
    	add(pos<<1|1,seg[pos].sum);
    	seg[pos].sum=0;
    	return;
    }
    inline void upgrade(re ll pos,re ll l,re ll r,re ll num)
    {
    	if(seg[pos].l>r||seg[pos].r<l)
    		return;
    	else if(seg[pos].l>=l&&seg[pos].r<=r)
    		return add(pos,num);
    	pushdown(pos);
    	upgrade(pos<<1,l,r,num);
    	upgrade(pos<<1|1,l,r,num);
    	pushup(pos);
    	return;
    }
    inline pair<ll,ll> query(re ll pos,re ll l,re ll r)
    {
    	if(seg[pos].l>=l&&seg[pos].r<=r)
    		return make_pair(seg[pos].val,seg[pos].minn);
    	else if(seg[pos].l>r||seg[pos].r<l)
    		return make_pair(0,inf);
    	pushdown(pos);
    	re pair<ll,ll> x=query(pos<<1,l,r),y=query(pos<<1|1,l,r);
    	re ll ans=0;
    	if(x.second==y.second)
    		ans+=x.first+y.first;
    	else if(x.second>y.second)
    		ans+=y.first;
    	else if(x.second<y.second)
    		ans+=x.first;
    	return make_pair(ans,min(x.second,y.second));
    }
    int main()
    {
    	read(n);
    	read(m);
    	for(re int i=1;i<=n;i++)
    		read(a[i]);
    	build(1,1,n);
    	for(re int i=1;i<=m;i++)
    	{
    		scanf("%s",s+1);
    		if(s[1]=='c')
    		{
    			read(x);
    			read(y);
    			re pair<ll,ll>temp=query(1,x,y);
    			if(!temp.second)
    				printf("%lld
    ",temp.first);
    			else
    				puts("0"); 
    		}
    		else if(s[1]=='a')
    		{
    			read(x);
    			read(y);
    			read(tmp);
    			upgrade(1,x,y,tmp);
    		}
    	}
    	exit(0);
    }
    
    
  • 相关阅读:
    全国省市县三级数据库
    多源教学数据管理系统之团队课设博客
    1.判断字符串中的字符是否Unique
    [转载]linux防火墙基础和管理设置iptables规则
    (转)Sed使用详解
    2.判断回文(Anagrams)
    【转载】关于23 种设计模式的有趣见解
    macbook M1芯片在centos8下安装k8s笔记
    Winform 学习初级 从WebForm到WinForm
    如何建立数据模型
  • 原文地址:https://www.cnblogs.com/CelticBlog/p/13531817.html
Copyright © 2011-2022 走看看