zoukankan      html  css  js  c++  java
  • CSUST 4005-你真的会!(分治思维+线段树)

    题目链接:http://acm.csust.edu.cn/problem/4005
    博客园食用链接:https://blog.csdn.net/qq_43906000/article/details/107815634

    Description

    给一个长度(n)的序列(a_i) 要进行(m)次操作,共有三种操作:

    (1.(L;R;V)) 表示区间([L,R])数值覆盖为(V)

    (2.(P;V))表示(a_p) 数值赋值为(V)

    (3.(L;R))表示询问询问(f(L,R))的值。

    注意:
    对于区间([L,R])的数字而言,(S_i)=在区间内任意选ii个数的乘积之和。

    (f(L,R)=(1+sum_{i=1}^{R-L+1}S_i)mod; 1e9+9)

    Input
    一行两个整数(n,m(1le n,mle 2e5))

    接下来一行(n)个整数表示(a_i(0le a_ile 1e9))

    接下来(m)行表示(m)次操作:

    输入格式为:

    (1;L;R;V, 1le Lle Rle n, 0le Vle 1e9)
    (2;P;V,1le Ple n,0le Vle 1e9)
    (3;L;R,(1le Lle Rle n))

    Output
    对每次(3)号操作输出一行一个整数表示答案。答案要对(1e9+9)取模。

    emmm,说是个签到题来着。。。如果单纯地盯着上面的(f(L,R)=(1+sum_{i=1}^{R-L+1}S_i)mod; 1e9+9)这一串式子,肯定是没有什么眉目的,我们看题目要求应该大概是个线段树,那么我们只需要考虑的是在线段树中将两颗子树合并后的结果和区间覆盖后的结果。那么对于每个节点,我们保存的值假设就是(val+1),那么我们考虑合并(x,y)两个值,他们合并之后就是(xy+x+y+1),可以看出就是两个数相乘加上两个数相加,那么似乎就是((x+1)*(y+1)),于是我们会惊讶地发现父节点的值就是两个儿子节点的乘积!

    接下来就是对于区间覆盖的处理了,那么就相当于(r-l+1)(x)的合并,那么就是((x+1)^{r-l+1})。似乎这题就结束了。

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define lc rt<<1
    #define rc rt<<1|1
    typedef long long ll;
    const int mac=2e5+10;
    const int mod=1e9+9;
    
    ll tree[mac<<2],lazy[mac<<2];
    
    ll qpow(ll a,ll b)
    {
    	ll ans=1; a%=mod;
    	while (b){
    		if (b&1) ans=ans*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return ans;
    }
    
    void build(int l,int r,int rt)
    {
    	lazy[rt]=-1;
    	if (l==r) {
    		scanf ("%d",&tree[rt]);
    		tree[rt]++;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson); build(rson);
    	tree[rt]=tree[lc]*tree[rc]%mod;
    }
    
    void push_down(int l,int r,int rt)
    {
    	int mid=(l+r)>>1;
    	lazy[lc]=lazy[rt]; lazy[rc]=lazy[rt];
    	tree[lc]=qpow(lazy[rt],mid-l+1);  tree[rc]=qpow(lazy[rt],r-mid);
    	lazy[rt]=-1;
    }
    
    void update(int l,int r,int rt,int L,int R,int val)
    {
    	if (l>=L && r<=R) {
    		lazy[rt]=val+1;
    		tree[rt]=qpow(val+1,r-l+1);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if (lazy[rt]!=-1) push_down(l,r,rt);
    	if (mid>=L) update(lson,L,R,val);
    	if (mid<R) update(rson,L,R,val);
    	tree[rt]=tree[lc]*tree[rc]%mod;
    }
    
    ll query(int l,int r,int rt,int L,int R)
    {
    	ll ans=1;
    	if (l>=L && r<=R) {return tree[rt];}
    	int mid=(l+r)>>1;
    	if (lazy[rt]!=-1) push_down(l,r,rt);
    	if (mid>=L) ans=ans*query(lson,L,R)%mod;
    	if (mid<R) ans=ans*query(rson,L,R)%mod;
    	return ans;
    }
    
    int main(int argc, char const *argv[])
    {
    	int n,m;
    	scanf ("%d%d",&n,&m);
    	build(1,n,1);
    	while (m--){
    		int opt,l,r,v,pos;
    		scanf ("%d",&opt);
    		if (opt==1){
    			scanf ("%d%d%d",&l,&r,&v);
    			update(1,n,1,l,r,v);
    		}
    		else if (opt==2){
    			scanf ("%d%d",&pos,&v);
    			update(1,n,1,pos,pos,v);
    		}
    		else {
    			scanf ("%d%d",&l,&r);
    			printf("%lld
    ",query(1,n,1,l,r));
    		}
    	}
    	return 0;
    }
    
    路漫漫兮
  • 相关阅读:
    leetcode计划(二)——ps:复习面试题计划+锻炼计划
    随感——简述码农办公提升工作效率的方法
    git——同步本地文件到github上
    算法数据结构——数的深搜和广搜(dfs和bfs)
    二分查找——没有想象中的容易(详解各种变式,超深度理解,c++)
    微软推出免费的Linux取证和Rootkit恶意软件检测服务
    美国采用人工智能领域来对抗种族偏见
    美联邦专家警告:黑客瞄准在家工作的美国人
    90后从白手起家到身价过亿,却坐地铁上班
    互联网巨头的人工智能野心,你看懂了吗?
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13440076.html
Copyright © 2011-2022 走看看