首页 > 其他分享 >P2023 [AHOI2009] 维护序列

P2023 [AHOI2009] 维护序列

时间:2024-02-20 20:34:18浏览次数:30  
标签:node return P2023 AHOI2009 ll nodey && 序列 410000

原题链接

code

#define ll long long
#include<bits/stdc++.h>
using namespace std;
ll tree[410000]={0};
ll wait_mul[410000]={0};
ll wait_add[410000]={0};
ll n,p;

inline void read(ll &x) {
    x = 0;
    ll flag = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-')flag = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    x *= flag;
}

inline void write(ll x)
{
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

void build(ll node,ll l,ll r)
{
    if(l==r)
    {
        read(tree[node]);
        return;
    }

    ll mid=(l+r)>>1;
    build(node<<1,l,mid);
    build((node<<1)+1,mid+1,r);
    tree[node] = (tree[node<<1] + tree[(node<<1)+1]) % p;
}

void fresh(int node, int l, int r) {
    tree[node] = (tree[node] * wait_mul[node] % p + (r - l + 1) * wait_add[node] % p) % p;//更新为待乘值乘上固定值加上待加值
    if (l != r)
    {
        wait_mul[node * 2] = wait_mul[node * 2] * wait_mul[node] % p;
        wait_add[node * 2] = (wait_add[node * 2] * wait_mul[node] % p + wait_add[node]) % p;//向下传的时候需要给待加值和待乘值同时乘上
        wait_mul[node * 2 + 1] = wait_mul[node * 2 + 1] * wait_mul[node] % p;
        wait_add[node * 2 + 1] = (wait_add[node * 2 + 1] * wait_mul[node] % p + wait_add[node]) % p;
    }
    wait_mul[node] = 1;
    wait_add[node] = 0;
}


void mul(ll node,ll l,ll r,ll x,ll y,ll c)
{
    fresh(node,l,r);
    if(r<x||l>y)return;

    if(l>=x&&r<=y)
    {
        wait_mul[node]=wait_mul[node]*c%p;
        wait_add[node]=wait_add[node]*c%p;
        fresh(node,l,r);
        return;
    }

    ll mid=(l+r)>>1;
    mul(node<<1,l,mid,x,y,c);
    mul((node<<1)+1,mid+1,r,x,y,c);
    tree[node]=(tree[node<<1]+tree[(node<<1)+1])%p;
}

void add(ll node,ll l,ll r,ll x,ll y,ll c)
{
    fresh(node,l,r);
    if(r<x||l>y)return;

    if(l>=x&&r<=y)
    {
        wait_add[node]=(wait_add[node]+c)%p;
        fresh(node,l,r);
        return;
    }

    ll mid=(l+r)>>1;
    add(node<<1,l,mid,x,y,c);
    add((node<<1)+1,mid+1,r,x,y,c);
    tree[node]=(tree[node<<1]+tree[(node<<1)+1])%p;
}

ll query(ll node,ll l,ll r,ll x,ll y)
{
    fresh(node,l,r);
    if(r<x||l>y)return 0;
    if(l>=x&&r<=y) return tree[node];

    ll mid=(l+r)>>1;
    return (query(node<<1,l,mid,x,y)+query((node<<1)+1,mid+1,r,x,y))%p;
}

int main()
{
    fill(wait_mul, wait_mul + 410000, 1);
    read(n); read(p);

    build(1,1,n);

    ll m;
    read(m);
    while(m--)
    {
        ll op;
        read(op);
        if(op==1)
        {
            ll l,r,c;
            read(l); read(r); read(c);
            mul(1,1,n,l,r,c);
        }
        else if(op==2)
        {
            ll l,r,c;
            read(l); read(r); read(c);
            add(1,1,n,l,r,c);
        }
        else
        {
            ll l,r;
            read(l); read(r);
            write(query(1,1,n,l,r)%p); putchar('\n');
        }
    }
    return 0;
}

标签:node,return,P2023,AHOI2009,ll,nodey,&&,序列,410000
From: https://www.cnblogs.com/pure4knowledge/p/18023985

相关文章

  • rust结构体包含另一个结构体引用时,serde序列化问题
    代码如下useserde::{Deserialize,Serialize};#[derive(Serialize,Deserialize)]structPerson{id:String,name:String,}#[derive(Serialize,Deserialize)]structMsg<'a>{id:String,person:&'aPerson,}fnmain(){......
  • DP19 最长公共子序列(一)C
    建议直接网上看思路....#include<stdio.h>intmax(inti,intj){if(i>j)returni;returnj;}intmaxlength[1001][1001];intmain(){intn,m;while(scanf("%d%d",&n,&m)!=EOF){charc=getchar();//读取换行char......
  • KY78 最大上升子序列和C++
    这个解决问题的思路使用动态规划,即用已知状态去得到未知状态。思路逻辑是这样sum[i]记录以A[i]为末上升子序列的和的最大值然后从j从0-i-1遍历如果A[j]<A[i]那么sum[i]=sum[j]+A[i];然后找出sum[i]中的的最大值,就是以A[i]为末上升子序列的和的最大值。这样就实现了从前......
  • day29 回溯算法part5 代码随想录算法训练营 491. 非递减子序列
    题目:491.非递减子序列我的感悟:难不怕,不行就抄一遍,再默写一遍,多记忆几遍。加油!!!理解难点:uset是本层的, res收获的是节点(满足要求的节点),不用return(用了return是仅仅收集叶子节点的)判断的逻辑,是nums[i]当前的节点和目标的path的区别代码示例:classSolution:......
  • P3411 序列变换 题解
    自己做不出来,看现在题解区的题解讲的都不咋清楚。懂了之后来为后人铺路。而且我的马蜂比较好看题目传送门我能看懂这道题,主要是依靠了这篇题解的帮助。首先我们只关注数的相对关系,所以可以离散化。注意到值域\(10^6\),用数组离散化。这道题可以用贪心做。(有一些定义先往下看)......
  • JAVA基础-序列化
    1,什么是序列化?Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。2,序列化的使用场景永久性保存对象,保存对的字节序列到本地文件或者数据库中;通过序列化以字节流的形式对象在网络中进行传递和接收;通过序列化在进程间传递......
  • 递增子序列--连续与不连续
    问题一:最长严格递增子序列的长度题目:给定一个整数数组nums,找到其中最长严格递增子序列的长度。状态定义:dp[i]表示以nums[i]结尾的最长严格递增子序列的长度。状态转移方程对于每个nums[i],遍历其之前的所有元素nums[j](j从0到i-1),如果nums[i]>nums[j],则可以考虑......
  • KY22 最大序列和C
    题目例子给的很好,还有不要遗漏全是负数的情况。#include<stdio.h>#include<math.h>intmain(){longlongn=0;while(scanf("%ld",&n)!=EOF){longlongsum=0;longlongmax=0;inttag=0;longlongmaxn=pow(-2,63);......
  • 代码随想录算法训练营第十八天 | 112. 路径总和,113. 路径总和ii ,106.从中序与后序遍
     513.找树左下角的值 已解答中等 相关标签相关企业 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层最左边 节点的值。假设二叉树中至少有一个节点。 示例1:输入:root=[2,1,3]输出:1示例2:输入:[1,2,3,4,null,5,6,n......
  • P2757 [国家集训队] 等差子序列
    题目的等差子序列最少只要求长度为3,那么其实就转化为对于一个数是否存在左右各一个与它差值相等的一对数,比如14325中1,5对3来说就如此。这样的关系放到数轴上就是是否存在一对数到某数的距离相等。由于题目明确是一个排列,也就是1到n所有数一定会出现一次,那么对于某数,它左边的......