zoukankan      html  css  js  c++  java
  • [bzoj1798][Ahoi2009]Seq 维护序列seq ([洛谷P3373]【模板】线段树 2)

    题目大意:有$n$个数,有$m$个操作,有三种:

    1. $1;l;r;x:$把区间$[l,r]$内的数乘上$x$
    2. $2;l;r;x:$把区间$[l,r]$内的数加上$x$
    3. $3;l;r:$询问区间$[l,r]$的和,对$p$取模

    (线段树2就是先读入$n;m;p$,再读入序列;本题是先读入$n;p$,读入序列,再读入$m$,双倍经验)

    题解:线段树,把$lazy\_tag$变成两个,分别记录区间加和区间乘,注意乘法的优先级比加法高

    卡点:无(我以前写的是什么代码啊?)



    C++ Code:

    #include <cstdio>
    #define maxn 100010 << 2
    long long V[maxn], cov[maxn], tg[maxn];
    int n, m;
    int s[maxn], L, R;
    long long p, x;
    void update(int rt) {
    	V[rt] = (V[rt << 1] + V[rt << 1 | 1]) % p;
    }
    void build(int rt, int l, int r) {
    	cov[rt] = 1;
    	if (l == r) {
    		V[rt] = s[l] % p;
    		return ;
    	}
    	int mid = l + r >> 1;
    	build(rt << 1, l, mid);
    	build(rt << 1 | 1, mid + 1, r);
    	update(rt);
    }
    void pushdown(int rt, long long len) {
    	long long &Cov = cov[rt], &Tg = tg[rt];
    	V[rt << 1] = (V[rt << 1] * Cov + Tg * (len + 1 >> 1)) % p;
    	V[rt << 1 | 1] = (V[rt << 1 | 1] * Cov + Tg * (len >> 1)) % p;
    	cov[rt << 1] = (cov[rt << 1] * Cov) % p;
    	cov[rt << 1 | 1] = (cov[rt << 1 | 1] * Cov) % p;
    	tg[rt << 1] = (tg[rt << 1] * Cov + Tg) % p;
    	tg[rt << 1 | 1] = (tg[rt << 1 | 1] * Cov + Tg) % p;
    	Cov = 1, Tg = 0;
    }
    void add1(int rt, int l, int r) {
    	if (L <= l && R >= r) {
    		V[rt] = (V[rt] * x) % p;
    		cov[rt] = (cov[rt] * x) % p;
    		tg[rt] = (tg[rt] * x) % p;
    		return ;
    	}
    	int mid = l + r >> 1;
    	if (cov[rt] != 1 || tg[rt]) pushdown(rt, r - l + 1);
    	if (L <= mid) add1(rt << 1, l, mid);
    	if (R > mid) add1(rt << 1 | 1, mid + 1, r);
    	update(rt);
    }
    void add2(int rt, int l, int r) {
    	if (L <= l && R >= r) {
    		V[rt] = (V[rt] + x * (r - l + 1ll)) % p;
    		tg[rt] = (tg[rt] + x) % p;
    		return ;
    	}
    	int mid = l + r >> 1;
    	if (cov[rt] != 1 || tg[rt]) pushdown(rt, r - l + 1);
    	if (L <= mid) add2(rt << 1, l, mid);
    	if (R > mid) add2(rt << 1 | 1, mid + 1, r);
    	update(rt);
    }
    long long ask(int rt, int l, int r) {
    	if (L <= l && R >= r) return V[rt] % p;
    	int mid = l + r >> 1;
    	long long ans = 0;
    	if (cov[rt] != 1 || tg[rt]) pushdown(rt, r - l + 1);
    	if (L <= mid) ans = ask(rt << 1, l, mid);
    	if (R > mid) ans = (ans + ask(rt << 1 | 1, mid + 1, r)) % p;
    	return ans;
    }
    int main() {
    	scanf("%d%lld", &n, &p);
    	for (int i = 1; i <= n; i++) scanf("%d", s + i);
    	build(1, 1, n);
    	scanf("%d", &m);
    	while (m --> 0) {
    		long long op;
    		scanf("%lld%d%d", &op, &L, &R);
    		switch (op) {
    			case 1: {
    				scanf("%lld", &x);
    				add1(1, 1, n);
    				break;
    			}
    			case 2: {
    				scanf("%lld", &x);
    				add2(1, 1, n);
    				break;
    			}
    			default: printf("%lld
    ", ask(1, 1, n));
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    关于PHP写的投票网站之刷票风云
    《暗战强人:黑客及反黑客工具快速精通》学习笔记
    《Linux信息安全实用教程》学习笔记
    MySql的入侵测试以及防范
    基于Sql Server 2008的分布式数据库的实践(终结)
    Sql Server的弱口令入侵测试以及防范
    IPC$ 测试与防范
    基于Sql Server 2008的分布式数据库的实践(五)
    基于Sql Server 2008的分布式数据库的实践(四)
    基于Sql Server 2008的分布式数据库的实践(三)
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9604816.html
Copyright © 2011-2022 走看看