• jzoj6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]


    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    赛时

    花了近2h来课这道题.
    发现了贪心规律,本想着可以水水70分。
    然鹅发现数据过大,似乎要打高精度?
    心态崩了,最后连20分都没拿到。
    后来才发现一个小小的性质,不用打高精度。
    太菜了。

    题解

    首先我们画画柿子。
    答案即为(sum_{i=l}^r a_i*2^{k_i})
    其中可以控制的就是那个k数组。
    考虑贪心。
    我们发现,对于一个正数,当然是希望它的k值越大。
    对于一个负数,当然希望它的k值越小。
    那么对于每个负数,它的k值最小为1(第一个位置为0)
    然后一段正数区间则是递增的。

    当然,这样是错误滴。为什么呢?我们有可能把一段正数区间乘2然后合并到前面的负数,这样答案会变大。
    这样一直合并合并之后,可能会出现的情况是:k数组会分成一个一个块,每块开头是1(第一块开头为0)然后向后面递增。

    所以我们从左到由依次加入数字,然后把当前的数字往前面合并,如果合并到最后当前块为负数就不合并了。
    但是数值要去模啊?怎么办?我们发现,负数不会特别小,最少是-2e9,那么只要正数大于4e9的时候就可以往前面疯狂合并即可。
    于是我们多记录一个数值表示当前块的数值堆4e9取min即可。

    拿到70分的好成绩。

    对于100分呢?
    我们离线询问,把询问按照有端点排序,然后依次加入数字,做与上面相同的东东。
    然后由于询问的左端点不是1,那么就不能直接统计了(废话)
    那么这个左端点必定把某一块分割成两个部分。
    求出这一块右边部分即可。

    那么问题来了:分割后两个部分右边的部分不会被合并吗?
    答案是:不会。
    因为我们发现,左端点所在的块右边的块的数值是小于0的(否则在做的过程中就已经合并了),我们知道,数值小于0是不能合并的,因此不会合并。

    那么利用并查集维护块或是线段树即可。

    标程

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    #include <cctype>
    using namespace std;
    const int maxn=500010;
    const long long mo=1000000007;
    
    struct node{
    	long long le,ri,kk,gg,lazy;
    };
    
    int n,m,l[maxn],r[maxn],gs,now;
    long long a[maxn],b[maxn],c[maxn],mi[maxn],sum[maxn],jl,jr,jk,jg;
    long long le[maxn],ri[maxn],k[maxn],zs[maxn],aa[maxn],qsum[maxn],col[maxn],id[maxn],wz[maxn],jll[maxn],qh[maxn],zd[maxn];
    node tree[4*maxn];
    
    void down_lazy(int x)
    {
    	if (tree[x].lazy==1)
    	{
    		tree[x*2].le=tree[x].le;
    		tree[x*2+1].le=tree[x].le;
    		tree[x*2].ri=tree[x].ri;
    		tree[x*2+1].ri=tree[x].ri;
    		tree[x*2].kk=tree[x].kk;
    		tree[x*2+1].kk=tree[x].kk;
    		tree[x*2].lazy=tree[x].lazy;
    		tree[x*2+1].lazy=tree[x].lazy;
    		tree[x*2].gg=tree[x].gg;
    		tree[x*2+1].gg=tree[x].gg;
    		tree[x].lazy=0;
    	}
    }
    
    void change(int x,int l,int r,int st,int en,int le,int ri,int kk,int g)
    {
    	if (l==st && r==en)
    	{
    		tree[x].le=le;
    		tree[x].ri=ri;
    		tree[x].kk=kk;
    		tree[x].gg=g;
    		tree[x].lazy=1;
    	}
    	else
    	{
    		down_lazy(x);
    		int mid=(l+r)/2;
    		if (mid>=en) change(x*2,l,mid,st,en,le,ri,kk,g);
    		else if (mid<st) change(x*2+1,mid+1,r,st,en,le,ri,kk,g);
    		else
    		{
    			change(x*2,l,mid,st,mid,le,ri,kk,g);
    			change(x*2+1,mid+1,r,mid+1,en,le,ri,kk,g);
    		}
    	}
    }
    
    void find(int x,int l,int r,int st)
    {
    	if (l==r)
    	{
    		jl=tree[x].le;
    		jr=tree[x].ri;
    		jk=tree[x].kk;
    		jg=tree[x].gg;
    	}
    	else
    	{
    		down_lazy(x);
    		int mid=(l+r)/2;
    		if (mid>=st) find(x*2,l,mid,st);
    		else find(x*2+1,mid+1,r,st);
    	}
    }
    
    long long min(long long a,long long b)
    {
    	if (a<b) return a;return b;
    }
    
    void qsort(int ll,int rr)
    {
    	int i=ll;int j=rr;
    	long long m=r[(i+j)/2];
    	while (i<=j)
    	{
    		while (r[i]<m) i++;
    		while (r[j]>m) j--;
    		if (i<=j)
    		{
    			swap(r[i],r[j]);
    			swap(l[i],l[j]);
    			swap(wz[i],wz[j]);
    			i++;j--;
    		}
    	}
    	if (ll<j) qsort(ll,j);
    	if (rr>i) qsort(i,rr); 
    }
    
    long long qsm(long long a,long long b)
    {
    	long long t=1;
    	long long y=a;
    	while (b>0)
    	{
    		if ((b&1)==1) t=t*y%mo;
    		y=y*y%mo;
    		b/=2;
    	}
    	return t;
    }
    
    int main()
    {
    //	freopen("data.in","r",stdin);
    //	freopen("data.out","w",stdout);
    	freopen("standard.in","r",stdin);
    	freopen("standard.out","w",stdout);
    	mi[0]=1;
    	for (int i=1;i<=500000;i++)
    	{
    		mi[i]=mi[i-1]*2%mo;
    	}
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%l64d",&a[i]);
    		zd[i]=(zd[i-1]+a[i]*mi[i]%mo)%mo;
    	}
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&l[i],&r[i]);
    	}
    	for (int i=1;i<=m;i++)
    	{
    		wz[i]=i;
    	}
    	qsort(1,m);
    	k[1]=0;le[1]=1;ri[1]=1;zs[1]=a[1];gs=1;aa[1]=a[1];qh[1]=(a[1]+mo)%mo;
    	change(1,1,n,le[gs],ri[gs],le[gs],ri[gs],k[gs],gs);
    	int op=1;
    	while (r[op]==1)
    	{
    		jll[wz[op]]=(qh[1]+mo)%mo;
    		op++;
    	}
    	for (int j=2;j<=n;j++)
    	{
    		long long zss=a[j]*2;long long aaa=a[j]*2%mo;
    		int kk=1;
    		if (a[j]>0)
    		{
    			while (gs>0 && zs[gs]+zss*mi[k[gs]]>0)
    			{
    				zss=min(5000000000,zs[gs]+zss*mi[k[gs]]);
    				aaa=(aa[gs]+aaa*mi[k[gs]]%mo+mo)%mo;
    				kk=kk+k[gs];
    				gs--;
    			}
    			if (gs==0)
    			{
    				gs++;
    			}
    			else
    			{
    				zss=min(5000000000,zs[gs]+zss*mi[k[gs]]);
    				aaa=(aa[gs]+aaa*mi[k[gs]]%mo+mo)%mo;
    				kk=k[gs]+kk;
    			}
    			ri[gs]=j;
    			k[gs]=kk;
    			zs[gs]=zss;
    			aa[gs]=aaa;
    			qh[gs]=(qh[gs-1]+aaa+mo)%mo;
    		}
    		else
    		{
    			gs++;
    			le[gs]=j;
    			ri[gs]=j;
    			zs[gs]=zss;
    			k[gs]=kk;
    			aa[gs]=aaa;
    			qh[gs]=(qh[gs-1]+aaa+mo)%mo;
    		}
    		change(1,1,n,le[gs],ri[gs],le[gs],ri[gs],k[gs],gs);
    		while (op<=m && j==r[op])
    		{
    			if (l[op]==r[op])
    			{
    				jll[wz[op]]=a[l[op]];
    				op++;
    			}
    			else
    			{
    				jr=0;jl=0;jk=0;jg=0;
    				if (l[op]>1)
    				{
    					find(1,1,n,l[op]-1);
    					jll[wz[op]]=(qh[gs]-qh[jg]+mo)%mo;
    					int opt=0;
    					if (jk==jr-jl+1) opt=1;
    					jll[wz[op]]=(jll[wz[op]]+(zd[jr]-zd[l[op]-1]+mo)%mo*qsm(mi[jr-(jk-(l[op]-jl))+opt],mo-2)%mo)%mo;
    					
    					int pd=jl;
    					jr=0;jl=0;jk=0;jg=0;
    					find(1,1,n,l[op]);
    					if (jl!=pd)
    					{
    						jll[wz[op]]=(jll[wz[op]]-(zd[jr]-zd[jl-1]+mo)%mo*qsm(mi[jr-jk+1],mo-2)%mo)%mo;
    					}
    					op++;
    				}
    				else
    				{
    					jll[wz[op]]=(qh[gs]+mo)%mo;
    					op++;
    				}
    			}
    		}
    	}
    	for (int i=1;i<=m;i++)
    	{
    		printf("%l64d
    ",(jll[i]+mo)%mo);
    	}
    }
    
  • 相关阅读:
    SpringBoot基础
    开始一个新的springboot项目checklist
    五项修炼: 终生学习者
    价值流分析-改进方法论
    伯努利方程
    会计语言
    svg蒙版mask
    从svg到计算机图形学
    xflux 调节屏幕色温
    处理器架构
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11628120.html
Copyright © 2020-2023  润新知