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;
    }
    
  • 相关阅读:
    iOS UIWebView中javascript与Objective-C交互、获取摄像头
    iOS UIWebView中javascript与Objective-C交互、获取摄像头
    android使用webview上传文件(支持相册和拍照)
    在Android浏览器中通过WebView调用相机拍照/选择文件 上传到服务器
    Android 访问权限设置
    perl 登入人人网
    攻击排查脚本
    利用套打和分栏巧妙来做商品价签
    perl 自定义请求头
    获取响应头信息
  • 原文地址:https://www.cnblogs.com/chdy/p/12890685.html
Copyright © 2011-2022 走看看