P2023 [AHOI2009]维护序列

题目描述

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

输入输出格式

输入格式:

第一行两个整数N和P(1≤P≤1000000000)。 第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。 第三行有一个整数M,表示操作总数。 从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出格式:

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

输入输出样例

输入样例#1: 复制

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

输出样例#1: 复制

2
35
8

说明

【样例说明】

初始时数列为(1,2,3,4,5,6,7)。

经过第1次操作后,数列为(1,10,15,20,25,6,7)。

对第2次操作,和为10+15+20=45,模43的结果是2。

经过第3次操作后,数列为(1,10,24,29,34,15,16}

对第4次操作,和为1+10+24=35,模43的结果是35。

对第5次操作,和为29+34+15+16=94,模43的结果是8。

测试数据规模如下表所示

数据编号 1 2 3 4 5 6 7 8 9 10

N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

Source: Ahoi 2009

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls l, mid, rt << 1
#define rs mid + 1, r, rt << 1 | 1
#define M mod
const int MAXN = 1000010;
struct f
{
    int l, r;
    ll len;
    ll t1, val, t2;
    //mu是维护乘积的懒惰标记,su是区间和,ad是加
    //要注意su和ad的区别
} tree[MAXN << 2]; //4倍空间
int n,i,op, m;
ll M;
void push_up(int rt)
{
    tree[rt].val = (tree[rt << 1].val + tree[rt << 1 | 1].val) % M;
}
void build(int l, int r, int rt)
{
    tree[rt].l = l; tree[rt].r = r; tree[rt].len = r - l + 1;
    tree[rt].t1=1; tree[rt].t2=0;
    if(l == r)
    {
        scanf("%lld", &tree[rt].val);
        return;
    }
    int mid = (l + r) >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}

void pushdown(int rt)
{
    tree[rt << 1].val = (tree[rt << 1].val * tree[rt].t1 % mod+ tree[rt << 1].len * tree[rt].t2 % mod) % mod;
    tree[rt << 1 | 1].val = (tree[rt << 1 | 1].val * tree[rt].t1 + tree[rt << 1 | 1].len * tree[rt].t2) % mod;
    tree[rt << 1].t1 = tree[rt << 1].t1 * tree[rt].t1 % mod;
    tree[rt << 1 | 1].t1 = tree[rt << 1 | 1].t1 * tree[rt].t1 % mod;
    tree[rt << 1].t2 = (tree[rt << 1 ].t2 * tree[rt].t1 + tree[rt].t2) % mod;
    tree[rt << 1 | 1].t2 = (tree[rt << 1 | 1].t2 * tree[rt].t1 + tree[rt].t2) % mod;
    tree[rt].t1 = 1;
    tree[rt].t2 = 0;
}
/*
void pushdown ( int rt) //维护su,mu和ad
{
    tree[rt << 1].val = ( tree[rt << 1].val * tree[rt].t1 + tree[rt].t2 * tree[rt << 1].len) % M;
    tree[rt << 1 | 1].val = ( tree[rt << 1 | 1].val * tree[rt].t1 + tree[rt].t2 * tree[rt << 1 | 1].len) % M;
    tree[rt << 1].t1 = tree[rt << 1].t1 * tree[rt].t1 % M;
    tree[rt << 1 | 1].t1 = tree[rt << 1 | 1].t1 * tree[rt].t1 % M;
   tree[rt << 1].t2 = ( tree[rt << 1].t2 * tree[rt].t1 + tree[rt].t2 ) % M;
    tree[rt << 1 | 1].t2 = ( tree[rt << 1 | 1].t2 * tree[rt].t1 + tree[rt].t2 ) % M;

    tree[rt].t1 = 1;
    tree[rt].t2 = 0;
}
*/
/*
void update (int x, int y ,int rt, int l, int r, ll k ,int flag)
{
    if ( x <= l && r <= y )
    {
    	if(flag == 1)
        {
            tree[rt].val = tree[rt].val * k % M;
            tree[rt].t1 = tree[rt].t1 * k % M;
            tree[rt].t2 = tree[rt].t2 * k % M;
        }
        else
        {
            tree[rt].t2 += k;
            if ( tree[rt].t2 >= M ) tree[rt].t2 -= M;
                tree[rt].val = ( tree[rt].val + tree[rt].len * k ) % M;
        }
        return;
    }
    pushdown ( rt );
    int mid = l + r >> 1;
    if ( x <= mid ) update (x, y , rt<< 1, l, mid, k ,flag);
    if ( mid < y ) update ( x, y,rt << 1 | 1, mid + 1, r, k,flag );
    push_up(rt);
}
*/

void update(int x, int y, int flag, ll k, int l, int r, int rt)
{
    if(l >= x && r <= y)
    {
        if(flag == 1)
        {
            tree[rt].val = tree[rt].val * k % mod;
            tree[rt].t1 = tree[rt].t1 * k % mod;
            tree[rt].t2 = tree[rt].t2 * k % mod;
        }
        else
        {
            tree[rt].val = (tree[rt].val + (tree[rt].len * k % mod)) % mod;
            tree[rt].t2 = (tree[rt].t2 + k) % mod;
        }
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(rt);
    if(mid >= x)
        update(x, y, flag, k, ls);
    if(mid < y)
        update(x, y, flag, k, rs);
    push_up(rt);
}

ll query ( int x, int y, int rt, int l, int r )
{
    if ( x <= l && r <= y )
        return tree[rt].val;
    pushdown ( rt);
    int mid = l + r >> 1;
    ll ans = 0;
    if ( x <= mid ) ans += query (x, y, rt << 1, l, mid );
    if ( mid < y ) ans += query ( x, y, rt << 1 | 1, mid + 1, r );
    if ( ans >= M ) ans -= M;
    push_up(rt);
    return ans;
}
int main()
{
    scanf("%d %lld",&n, &M);
    //cout << "!" << endl;
    build ( 1, n ,1 );
    //cout << "!" << endl;
    scanf("%d", &m);
    //cout << "!" << endl;
    while ( m-- )
    {
    	int x, y;
    	//cout << "!" << endl;
        scanf("%d %d %d",&op, &x, &y);
        //cout << "!" << endl;
        if(op == 1 || op == 2)
        {
        	ll temp;
        	scanf("%lld", &temp);
        	// update(x, y, 1, 1, n, temp,op);
            update(x, y, op, temp, 1, n, 1);
        }
        else
            printf ( "%lld\n", query (x, y, 1, 1, n ) );
    }
}

猜你喜欢

转载自blog.csdn.net/Ant_e_zz/article/details/81532491
今日推荐