zoukankan      html  css  js  c++  java
  • CF 878E Numbers on the blackboard 并查集 离线 贪心

    LINK:Numbers on the blackboard

    看完题觉得很难。

    想了一会发现有点水 又想了一下发现有点困难。

    最终想到了 但是实现的时候 也很难.

    先观察题目中的这个形式 使得前后两个数字变成x+2y.

    那么一个数字的变成两倍的次数固定 除了左端点至少可以变化一次.

    有些数字 可以变换多次 这取决于什么 容易考虑到右端点 先变化一次 如果>0显然 可以和其左边进行合并一下.

    然后 可以变换更多次 然后从右到左考虑这个过程就发现是正确的了.

    这样 我们得到了一个nm的做法.

    容易发现这个东西不具有区间可加性 所以不能采用线段树来维护这个东西.

    不过这个过程是从左到右做的 考虑离线处理这个问题.

    对于每个右端点处理左端点 显然中间的合并过程可以单调栈做一下.

    考虑计算答案 单调栈存一个前缀和 然后在左端点所在区间内 再求一下值即可.

    这个值可以利用线段树来做 当然也可以不需要 倒着预处理的后缀和就可以了.

    一个难点是 比大小的时候可能会爆long long 这里可以预估一个INF 来防止爆掉.

    也算是常见套路吧. 代码写的比较丑 因为 状态相当的不好.

    const ll MAXN=100010;
    ll n,m,cnt,top;
    ll a[MAXN],ans[MAXN],f[MAXN],l[MAXN],r[MAXN],s[MAXN],id[MAXN];
    ll qz[MAXN],hz[MAXN],mi[MAXN],INV[MAXN],w[MAXN],fac[MAXN],c[MAXN];
    struct wy
    {
    	ll id;
    	ll l,r;
    }t[MAXN];
    inline ll inv(ll x)
    {
    	return x==1?x:inv(mod%x)*(mod-mod/x)%mod;
    }
    inline ll cmp(wy a,wy b){return a.r<b.r;}
    inline int getfather(int x){return x==f[x]?x:f[x]=getfather(f[x]);}
    inline ll ksm(ll b,ll p)
    {
    	ll cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=cnt*b%mod;
    		b=b*b%mod;p=p>>1;
    	}
    	return cnt;
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	get(n);get(m);mi[0]=1;fac[0]=1;
    	rep(1,n,i)get(a[i]),l[i]=r[i]=f[i]=i,fac[i]=fac[i-1]*2%mod,mi[i]=min(mi[i-1]*2,INF);
    	INV[n]=inv(fac[n]);hz[n]=a[n]*2%mod;
    	fep(n-1,0,i)INV[i]=INV[i+1]*2%mod,hz[i]=(hz[i+1]+a[i])*2%mod;
    	rep(1,m,i)
    	{
    		ll l,r;
    		get(l);get(r);
    		ans[i]=a[l];
    		if(l==r)continue;
    		t[++cnt]=(wy){i,l+1,r};
    	}
    	sort(t+1,t+1+cnt,cmp);
    	ll flag=1;s[++top]=1;qz[top]=w[top]=a[1];id[1]=1;
    	rep(2,n,i)
    	{
    		//当前端点向右移动.
    		ll fa=i;ll ww=a[i]*2,ss=a[i]*2;
    		while(top!=1&&ww>0)
    		{
    			if(ww!=INF)//更新当前块的比较值.
    			{
    				if(mi[(r[s[top]]-l[s[top]]+1)]==INF)ww=INF;
    				else
    				{
    					if(ww>=(INF-1)/mi[(r[s[top]]-l[s[top]]+1)]+1)ww=INF;
    					else ww=ww*mi[(r[s[top]]-l[s[top]]+1)];
    				}
    			}
    			ss=ss*fac[(r[s[top]]-l[s[top]]+1)]%mod;
    			if(ww!=INF)ww=min(INF,ww+w[top]);
    			f[fa]=s[top];ss=(ss+qz[top]-qz[top-1]+mod)%mod;
    			r[s[top]]=r[fa];fa=s[top];--top;
    		}
    		s[++top]=fa;qz[top]=(qz[top-1]+ss)%mod;w[top]=ww;id[fa]=top;
    		while(flag<=cnt&&t[flag].r==i)
    		{
    			ll xx=getfather(t[flag].l);
    			ans[t[flag].id]=(ans[t[flag].id]+qz[top]-qz[id[xx]]+mod)%mod;
    			ww=hz[t[flag].l]-hz[r[xx]+1]*fac[r[xx]+1-t[flag].l];
    			ans[t[flag].id]=(ans[t[flag].id]+ww)%mod;
    			++flag;
    		}
    	}
    	rep(1,m,i)putl((ans[i]+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    java读取配置文件 xml properties的几种方法
    aix source 命令
    解决连接ORACLE错误一例:ORA01033: ORACLE 正在初始化或关闭
    oracle database character set
    spring junit 测试
    Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php
    Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer
    Atitit.木马病毒 webftp 的原理跟个设计
    Atitit.js this错误指向window的解决方案
    Atitit.反编译apk android源码以及防止反编译apk
  • 原文地址:https://www.cnblogs.com/chdy/p/12890685.html
Copyright © 2011-2022 走看看