zoukankan      html  css  js  c++  java
  • Loj 2028 随机序列

    Loj 2028 随机序列

    • 连续的乘号会将序列分成若干个块,块与块之间用加减号连接:

    [(a_1*a_2*...a_i)pm(a_{i+1}*a_{i+2}*...a_j)pm... ]

    • 除去所有都是乘号的一种,对于任意一个序列,总有与之对应唯一的另一个序列,它们所有的加减号都相反.
    • 把这两个序列的和相加,就只剩下了 (2*(a_1*a_2*...a_i)),其中 (i) 为第一个加减号之前的位置.
    • 那么平均下来,相当于每个序列的贡献为 ((a_1*a_2*...a_i)).
    • 考虑对每个 (i) ,前面填入了 (i-1) 个乘号,相邻的必须是加减号,后面 (n-i-1) 个符号随便填,共有 (2*3^{n-i-1}) 种.
    • 那么用线段树对于 ([1,n-1]) 维护 (v_i=3^{n-i-1}*2*prod_{j=1}^i a_i) 的和,答案即为

    [(prod_{i=1}^{n}a_i)+(sum_{i=1}^{n-1}v_i). ]

    • 将位置 (i) 的数从 (a) 改为 (b) ,相当于对区间 ([i,n-1]) 乘了 (frac b a) .显然容易实现.
    • 注意修改位置 (n) 上的数时不用区间修改.否则 (L>R) ,会炸.
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    inline int read()
    {
    	int x=0;
    	bool pos=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())
    		if(ch=='-')
    			pos=0;
    	for(;isdigit(ch);ch=getchar())
    		x=x*10+ch-'0';
    	return pos?x:-x;
    }
    const int P=1e9+7;
    const int MAXN=1e5+10;
    const int MAXV=1e4;
    int n,m;
    inline int add(int a,int b)
    {
    	return (a + b) % P;
    }
    inline int mul(int a,int b)
    {
    	return 1LL * a * b % P;
    }
    int fpow(int a,int b)
    {
    	int res=1;
    	while(b)
    		{
    			if(b&1)
    				res=mul(res,a);
    			a=mul(a,a);
    			b>>=1;
    		}
    	return res;
    }
    int inv[MAXV+10],Pow[MAXN];
    int a[MAXN],prod[MAXN];
    struct node{
    	int l,r;
    	int sum,tag;
    	node()
    		{
    			tag=1;
    		}
    }Tree[MAXN<<2];
    #define root Tree[o]
    #define lson Tree[o<<1]
    #define rson Tree[o<<1|1]
    void pushup(int o)
    {
    	root.sum=add(lson.sum,rson.sum);
    }
    void BuildTree(int o,int l,int r)
    {
    	root.l=l,root.r=r;
    	if(l==r)
    		{
    			//fpow(3,n-l-1) Pow[n-l-1]
    			int tmp=mul(Pow[n-l-1],2);
    			tmp=mul(tmp,prod[l]);
    			root.sum=tmp;
    			return;
    		}
    	int mid=(l+r)>>1;
    	BuildTree(o<<1,l,mid);
    	BuildTree(o<<1|1,mid+1,r);
    	pushup(o);
    }
    void Modifiy(int o,int c)
    {
    	root.sum=mul(root.sum,c);
    	root.tag=mul(root.tag,c);
    }
    void pushdown(int o)
    {
    	if(root.tag!=1)
    		{
    			Modifiy(o<<1,root.tag);
    			Modifiy(o<<1|1,root.tag);
    			root.tag=1;
    		}
    }
    void update(int o,int L,int R,int c)
    {
    	int l=root.l,r=root.r;
    	if(l>R || r<l)
    		return;
    	if(L<=l && r<=R)
    		{
    			Modifiy(o,c);
    			return;
    		}
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(L<=mid)
    		update(o<<1,L,R,c);
    	if(R>mid)
    		update(o<<1|1,L,R,c);
    	pushup(o);
    }
    void init()
    {
    	inv[1]=1;
    	for(int i=2;i<=MAXV;++i)
    		inv[i]=mul(P-P/i,inv[P%i]);
    	Pow[0]=1;
    	for(int i=1;i<=n;++i)
    		Pow[i]=mul(Pow[i-1],3);
    }
    int main()
    {
    	n=read(),m=read();
    	init();
    	prod[0]=1;
    	for(int i=1;i<=n;++i)
    		prod[i]=mul(prod[i-1],a[i]=read());
    	BuildTree(1,1,n-1);
    	while(m--)
    		{
    			int i=read(),v=read();
    			int c=mul(v,inv[a[i]]);
    			a[i]=v;
    			prod[n]=mul(prod[n],c);
    			if(i<=n-1)
    				update(1,i,n-1,c);
    			int ans=add(Tree[1].sum,prod[n]);
    			printf("%d
    ",ans);
    		}
    	return 0;
    }
    
  • 相关阅读:
    Linux系统管理10-----进程和计划任务管理
    07作业进程和任务管理
    Linux系统管理09-----引导过程与服务过程
    网站部署流程
    Docker 安装与使用
    基于NFS共享实现kvm虚拟主机
    GlusterFS 部署
    rsync 远程同步服务部署
    Zabbix 通过 JMX 监控 tomcat
    Zabbix 简单错误 解决方法
  • 原文地址:https://www.cnblogs.com/jklover/p/10398010.html
Copyright © 2011-2022 走看看