Logo 铜龟的博客

博客

悬赏

2023-07-30 21:44:24 By 铜龟

悬赏洛谷P3373,悬赏3个样例(任意);

一下是题面(量力而行);

【模板】线段树 2

题目描述

如题,已知一个数列,你需要进行下面三种操作:

  • 将某区间每一个数乘上 $x$;
  • 将某区间每一个数加上 $x$;
  • 求出某区间每一个数的和。

输入格式

第一行包含三个整数 $n,q,m$,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 $n$ 个用空格分隔的整数,其中第 $i$ 个数字表示数列第 $i$ 项的初始值。

接下来 $q$ 行每行包含若干个整数,表示一个操作,具体如下:

操作 $1$: 格式:1 x y k 含义:将区间 $[x,y]$ 内每个数乘上 $k$

操作 $2$: 格式:2 x y k 含义:将区间 $[x,y]$ 内每个数加上 $k$

操作 $3$: 格式:3 x y 含义:输出区间 $[x,y]$ 内每个数的和对 $m$ 取模所得的结果

输出格式

输出包含若干行整数,即为所有操作 $3$ 的结果。

样例 #1

样例输入 #1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

样例输出 #1

17
2

提示

【数据范围】

对于 $30\%$ 的数据:$n \le 8$,$q \le 10$。
对于 $70\%$ 的数据:$n \le 10^3 $,$q \le 10^4$。
对于 $100\%$ 的数据:$1 \le n \le 10^5$,$1 \le q \le 10^5$。

除样例外,$m = 571373$。

(数据已经过加强 ^_^)

故输出应为 $17$、$2$($40 \bmod 38 = 2$)。

以上是题面

首先给出ACcode和清晰题解者将获得免费的三个样例(我给)。

主要在区间乘法的地方不知道怎么做。大家可以看看我P3372线段数1的代码:

#include<iostream>
#include<cmath>
#define int long long
using namespace std;
int n,m;
int mov,x,y,k;
struct node{
    int left;
    int right;
    int sum;
    int l,r;
    int lazy;
}tree[400005];
int num[100005];
inline int read(){
    int ret=1,k=0;
    char c=getchar();
    while(c<'0' or c>'9'){if(c=='-'){ret = -1;}c=getchar();}
    while(c>='0' and c<='9'){k=k*10+c-'0';c=getchar();}
    return ret*k;
}
inline void write(int n){
    if(n>9){
        write(n/10);
    }
    putchar(n%10+'0');
}
int build(int pos,int l,int r){
    if(l==r){
        tree[pos].l=l;
        tree[pos].r=r;
        tree[pos].sum=num[(l+r)/2];
        return num[(l+r)/2];
    }
    int a=build(pos*2,l,(l+r)/2);
    int b=build(pos*2+1,(l+r)/2+1,r);
    tree[pos].left=pos*2;
    tree[pos].right=pos*2+1;
    tree[pos].sum=a+b;
    tree[pos].l=l;
    tree[pos].r=r;
    return a+b;
}

void push_down(int x)
{
    if(tree[x].lazy == 0) return;
    int le = tree[x].left, ri = tree[x].right, lz = tree[x].lazy;
    tree[le].lazy += lz, tree[ri].lazy += lz;
    tree[le].sum += lz * (tree[le].r - tree[le].l + 1);
    tree[ri].sum += lz * (tree[ri].r - tree[ri].l + 1);
    tree[x].lazy = 0;
} 

void add(int pos){
    if(tree[pos].l > y || tree[pos].r < x) return; 
    if((x<=tree[pos].l and y>=tree[pos].r)){
        tree[pos].lazy+=k;
        tree[pos].sum+=(tree[pos].r-tree[pos].l + 1)*k;
        return;
    }
//    if(tree[pos].lazy>0){
//        tree[tree[pos].left].lazy+=tree[pos].lazy,tree[tree[pos].left].sum+=tree[tree[pos].left].lazy*(tree[tree[pos].left].r-tree[tree[pos].left].l + 1);
//        tree[tree[pos].right].lazy+=tree[pos].lazy,tree[tree[pos].right].sum+=tree[tree[pos].right].lazy*(tree[tree[pos].right].r-tree[tree[pos].right].l + 1);
//        tree[pos].lazy=0;
//    }
    push_down(pos);
    add(tree[pos].left);//递归下降
    add(tree[pos].right);//递归下降
    tree[pos].sum = tree[tree[pos].left].sum + tree[tree[pos].right].sum;
}
int ask(int pos){
    if(tree[pos].l > y || tree[pos].r < x) return 0; 
    if((x<=tree[pos].l and y>=tree[pos].r)){
        return tree[pos].sum;
    }
//    if(tree[pos].lazy>0){
//        tree[tree[pos].left].lazy+=tree[pos].lazy,tree[tree[pos].left].sum+=tree[tree[pos].left].lazy*(tree[tree[pos].left].r-tree[tree[pos].left].l + 1);
//        tree[tree[pos].right].lazy+=tree[pos].lazy,tree[tree[pos].right].sum+=tree[tree[pos].right].lazy*(tree[tree[pos].right].r-tree[tree[pos].right].l + 1);
//        tree[pos].lazy=0;
//    }
    push_down(pos);
    int ret=0;
    ret+=ask(tree[pos].left);//递归下降
    ret+=ask(tree[pos].right);//递归下降
    return ret;
}
signed main(){
    n=read();
    m=read();
    for(int i = 1;i <= n;i++){
        num[i]=read();
    }
    build(1,1,n);

    while(m--){
        mov=read();
        if(mov==1){
            x=read(),y=read(),k=read();
            add(1);
        }else{
            x=read(),y=read();
            write(ask(1));
            putchar('\n');
        }
    }
    return 0;
}

以上我没有抄题解。我自己写的。

这是P3372的代码。求P3373思路和ACcode!!!

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。