华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1173|回复: 4
打印 上一主题 下一主题

P3373 【模板】线段树 2

[复制链接]

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
跳转到指定楼层
楼主
发表于 2018-5-13 01:11:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P3373

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

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入输出格式
输入格式:
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

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

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

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

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

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

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

输入输出样例
输入样例#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
说明
时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

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

样例说明:



回复

使用道具 举报

2

主题

105

帖子

306

积分

中级会员

Rank: 3Rank: 3

积分
306
沙发
发表于 2018-7-29 19:35:52 | 只看该作者
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <map>
  6. #include <string>
  7. #include <vector>
  8. #include <queue>
  9. #include <stack>
  10. #include <cstdio>
  11. #include <cstdlib>
  12. using namespace std;
  13. const int N = 2e5 + 10;
  14. typedef long long LL;
  15. LL sum[N * 4]= {0}, tag_add[N * 4]= {0}, tag_mul[N * 4]= {0},a[N],mo;
  16. void build(int l, int r, int o)
  17. {
  18.     if(l == r)
  19.     {
  20.         sum[o] = a[l];
  21.         tag_add[o] = 0,tag_mul[o]=1;
  22.         return ;
  23.     }
  24.     int mid = (l + r) >> 1;
  25.     build(l, mid, o * 2);
  26.     build(mid + 1, r, o << 1 | 1);
  27.     sum[o] = (sum[o << 1] + sum[o << 1 | 1])%mo;
  28.     tag_add[o] = 0,tag_mul[o]=1;
  29.     return ;
  30. }
  31. void update_mul(int L, int R, LL mul, int l, int r, int o)
  32. {
  33.     if(L <= l && r <= R)
  34.     {
  35.         (sum[o] *= mul)%=mo;
  36.         (tag_mul[o] *= mul)%=mo;
  37.         (tag_add[o] *= mul)%=mo;
  38.         return ;
  39.     }
  40.     int mid = (l + r) >> 1;
  41.     if(tag_mul[o]!=1)
  42.     {
  43.         (sum[o << 1] *= tag_mul[o])%=mo;
  44.         (tag_mul[o << 1] *= tag_mul[o])%=mo;
  45.         (tag_add[o << 1] *= tag_mul[o])%=mo;
  46.         (sum[o << 1|1] *= tag_mul[o])%=mo;
  47.         (tag_mul[o << 1|1] *= tag_mul[o])%=mo;
  48.         (tag_add[o << 1|1] *= tag_mul[o])%=mo;
  49.         tag_mul[o] = 1;
  50.     }
  51.     if(tag_add[o])
  52.     {
  53.         (sum[o << 1] += tag_add[o] * (mid - l + 1))%=mo;
  54.         (tag_add[o << 1] += tag_add[o])%=mo;
  55.         (sum[o << 1|1] += tag_add[o] * (r - mid))%=mo;
  56.         (tag_add[o << 1|1] += tag_add[o])%=mo;
  57.         tag_add[o] = 0;
  58.     }
  59.     if(L <= mid) update_mul(L, R, mul, l, mid, o << 1);
  60.     if(R > mid) update_mul(L, R, mul, mid + 1, r, o << 1 | 1);
  61.     sum[o] = (sum[o << 1] + sum[o << 1 | 1])%mo;
  62. }
  63. void update_add(int L, int R, LL add, int l, int r, int o)
  64. {
  65.     if(L <= l && r <= R)
  66.     {
  67.         (sum[o] += add * (r - l + 1))%=mo;
  68.         (tag_add[o] += add)%=mo;
  69.         return ;
  70.     }
  71.     int mid = (l + r) >> 1;
  72.     if(tag_mul[o]!=1)
  73.     {
  74.         (sum[o << 1] *= tag_mul[o])%=mo;
  75.         (tag_mul[o << 1] *= tag_mul[o])%=mo;
  76.         (tag_add[o << 1] *= tag_mul[o])%=mo;
  77.         (sum[o << 1|1] *= tag_mul[o])%=mo;
  78.         (tag_mul[o << 1|1] *= tag_mul[o])%=mo;
  79.         (tag_add[o << 1|1] *= tag_mul[o])%=mo;
  80.         tag_mul[o] = 1;
  81.     }
  82.     if(tag_add[o])
  83.     {
  84.         (sum[o << 1] += tag_add[o] * (mid - l + 1))%=mo;
  85.         (tag_add[o << 1] += tag_add[o])%=mo;
  86.         (sum[o << 1|1] += tag_add[o] * (r - mid))%=mo;
  87.         (tag_add[o << 1|1] += tag_add[o])%=mo;
  88.         tag_add[o] = 0;
  89.     }
  90.     if(L <= mid) update_add(L, R, add, l, mid, o << 1);
  91.     if(R > mid) update_add(L, R, add, mid + 1, r, o << 1 | 1);
  92.     sum[o] = (sum[o << 1] + sum[o << 1 | 1])%mo;
  93. }
  94. LL query(int L, int R, int l, int r, int o)
  95. {
  96.     if(L <= l && r <= R)
  97.     {
  98.         return sum[o];
  99.     }
  100.     int mid = (l + r) >> 1;
  101.     if(tag_mul[o]!=1)
  102.     {
  103.         (sum[o << 1] *= tag_mul[o])%=mo;
  104.         (tag_mul[o << 1] *= tag_mul[o])%=mo;
  105.         (tag_add[o << 1] *= tag_mul[o])%=mo;
  106.         (sum[o << 1|1] *= tag_mul[o])%=mo;
  107.         (tag_mul[o << 1|1] *= tag_mul[o])%=mo;
  108.         (tag_add[o << 1|1] *= tag_mul[o])%=mo;
  109.         tag_mul[o] = 1;
  110.     }
  111.     if(tag_add[o])
  112.     {
  113.         (sum[o << 1] += tag_add[o] * (mid - l + 1))%=mo;
  114.         (tag_add[o << 1] += tag_add[o])%=mo;
  115.         (sum[o << 1|1] += tag_add[o] * (r - mid))%=mo;
  116.         (tag_add[o << 1|1] += tag_add[o])%=mo;
  117.         tag_add[o] = 0;
  118.     }
  119.     LL ans = 0;
  120.     if(L <= mid) ans += query(L, R, l, mid, o << 1);
  121.     if(R > mid) ans += query(L, R, mid + 1, r, o << 1 | 1);
  122.     return ans%mo;
  123. }

  124. int main()
  125. {
  126.     int n, m;
  127.     scanf("%d %d %lld", &n, &m,&mo);
  128.     for(int i=1; i<=n; i++)
  129.         scanf("%lld", &a[i]);
  130.     build(1, n, 1);
  131.     while(m --)
  132.     {
  133.         int op;
  134.         scanf("%d", &op);
  135.         if(op == 1)
  136.         {
  137.             int l, r;
  138.             LL x;
  139.             scanf("%d %d %lld", &l, &r, &x);
  140.             update_mul(l, r, x, 1, n, 1);
  141.         }
  142.         else if(op == 2)
  143.         {
  144.             int l, r;
  145.             LL x;
  146.             scanf("%d %d %lld", &l, &r, &x);
  147.             update_add(l, r, x, 1, n, 1);
  148.         }
  149.         else
  150.         {
  151.             int l, r;
  152.             scanf("%d %d", &l, &r);
  153.             printf("%lld\n", query(l, r, 1, n, 1));
  154.         }
  155.     }
  156. }
复制代码
回复 支持 反对

使用道具 举报

0

主题

31

帖子

94

积分

注册会员

Rank: 2

积分
94
板凳
发表于 2018-7-30 10:33:25 | 只看该作者
  1. #include<cstdio>
  2. int n,m,mod;
  3. int a[100000+100];
  4. struct node
  5. {
  6.         int l;int r;int sum;int tagsum;int tagmul;
  7. }tree[400000+100];
  8. int k,start,end;
  9. void pushdown(int root)
  10. {
  11.         tree[root*2].tagsum=(tree[root].tagsum+tree[root*2].tagsum*tree[root].tagmul)%mod;
  12.     tree[root*2+1].tagsum=(tree[root].tagsum+tree[root*2+1].tagsum*tree[root].tagmul)%mod;
  13.     tree[root*2].tagmul=(tree[root*2].tagmul*tree[root].tagmul)%mod;
  14.     tree[root*2+1].tagmul=(tree[root*2+1].tagmul*tree[root].tagmul)%mod;
  15.     tree[root*2].sum=(tree[root*2].sum*tree[root].tagmul+tree[root].tagsum*(tree[root*2].r-tree[root*2].l+1))%mod;
  16.     tree[root*2+1].sum=(tree[root*2+1].sum*tree[root].tagmul+tree[root].tagsum*(tree[root*2+1].r-tree[root*2+1].l+1))%mod;
  17.     tree[root].tagsum=0;
  18.     tree[root].tagmul=1;
  19. }
  20. void setup(int root,int s,int e)
  21. {
  22.         tree[root].l=s;
  23.         tree[root].r=e;
  24.         tree[root].tagsum=0;
  25.         tree[root].tagmul=1;
  26.         if(s==e)
  27.         {
  28.                 tree[root].sum=a[s];
  29.         }
  30.         else
  31.         {
  32.                 setup(root*2,s,(s+e)/2);
  33.                 setup(root*2+1,(s+e)/2+1,e);
  34.                 tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
  35.         }
  36. }
  37. void update(int root,int s,int e,int flag,int num)
  38. {
  39.         pushdown(root);
  40.         if(flag==1&&tree[root].l>=s&&tree[root].r<=e)
  41.         {
  42.                 tree[root].tagmul=(tree[root].tagmul*num)%mod;
  43.                 tree[root].tagsum=(tree[root].tagsum*num)%mod;
  44.                 tree[root].sum=(tree[root].tagmul*tree[root].sum)%mod;
  45.                 return;
  46.         }
  47.         if(flag==2&&tree[root].l>=s&&tree[root].r<=e)
  48.         {
  49.                 tree[root].tagsum=(tree[root].tagsum+num)%mod;
  50.         tree[root].sum=(tree[root].sum+tree[root].tagsum*(tree[root].r-tree[root].l+1))%mod;
  51.         return;
  52.         }
  53.         int mid=(tree[root].l+tree[root].r)/2;
  54.         if(s<=mid)
  55.         {
  56.                 update(root*2,s,e,flag,num);
  57.         }
  58.         if(e>=mid+1)
  59.         {
  60.                 update(root*2+1,s,e,flag,num);
  61.         }
  62.         tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
  63. }
  64. int findout(int root,int s,int e)
  65. {
  66.         pushdown(root);
  67.         if(tree[root].l>=s&&tree[root].r<=e)
  68.         {
  69.                 return tree[root].sum%mod;
  70.         }
  71.         int mid=(tree[root].l+tree[root].r)/2;
  72.         return ((s<=mid?findout(root*2,s,e):0)+(e>mid?findout(root*2+1,s,e):0))%mod;
  73. }
  74. int main()
  75. {
  76.         scanf("%d%d%d",&n,&m,&mod);
  77.         for(int i=1;i<=n;i++)
  78.         {
  79.                 scanf("%d",&a[i]);
  80.         }
  81.         setup(1,1,n);
  82.         for(int i=1;i<=m;i++)
  83.         {
  84.                 scanf("%d",&k);
  85.                 if(k==1||k==2)
  86.                 {
  87.                         int x;
  88.                         scanf("%d%d%d",&start,&end,&x);
  89.                         update(1,start,end,k,x);
  90.                 }
  91.                 else
  92.                 {
  93.                         if(k==3)
  94.                         {
  95.                                 scanf("%d%d",&start,&end);
  96.                                 printf("%d\n",findout(1,start,end));
  97.                         }
  98.                 }
  99.         }
  100.         return 0;
  101. }
复制代码

好像很TM腐朽啊,线段树是体力活
回复 支持 反对

使用道具 举报

9

主题

26

帖子

111

积分

禁止发言

积分
111
地板
发表于 2018-8-16 21:57:25 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-12-27 16:54 , Processed in 0.105020 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表