mod

【题目描述】
给定一个长度为 n 的非负整数序列 a,你需要支持以下操作:
1:给定 l,r,输出 a[l]+a[l+1]+...+a[r]。
2:给定 l,r,x,将 a[l],a[l+1],...,a[r]对 x 取模。
3:给定 k,y,将 a[k]修改为 y。
【输入数据】
第一行两个整数 n,m。第二行 n 个整数 a[1]~a[n]。接下来 m 行每
行 3 或 4 个整数表示操作。
【输出数据】
对于每个操作 1,输出一行一个整数表示答案。
【样例输入】
5 5
1 2 3 4 5
2 3 5 4
3 3 5
1 2 5
2 1 3 3
1 1 3
【样例输出】
8
5【数据范围】
对于 40%的数据,n,m<=1000。
对于 100%的数据, n,m<=100000,
1<=l<=r<=n,
1<=k<=n,
1<=x<=10^9,
0<=a[i],y<=10^9。

用线段树维护区间最大值以及区间和。
进行取模操作时,如果 x>区间最大值那么退出,否则两
边都递归下去。
单个数被有效地取模一次只会花费 O(logn)的时间,并且
数值至少减半,因此每次修改至多使时间复杂度增加
O(logn^2)。
时间复杂度 O(mlogn^2)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long lol;
 7 lol a[100001],c[400001],s[400001];
 8 int n,m,opt;
 9 void build(int rt,int l,int r)
10 {
11   if (l==r)
12     {
13       c[rt]=a[l];
14       s[rt]=a[l];
15       return;
16     }
17   int mid=(l+r)/2;
18   build(rt*2,l,mid);
19   build(rt*2+1,mid+1,r);
20   c[rt]=max(c[rt*2],c[rt*2+1]);
21   s[rt]=s[rt*2]+s[rt*2+1];
22 }
23 void update(int rt,int l,int r,int L,int R,lol d)
24 {
25   if (l==r)
26     {
27       c[rt]=c[rt]%d;
28       s[rt]%=d;
29       return;
30     }
31   if (l>=L&&r<=R)
32     {
33       if (c[rt]<d)
34     return;
35     }
36   int mid=(l+r)/2;
37   if (L<=mid) update(rt*2,l,mid,L,R,d);
38   if (R>mid) update(rt*2+1,mid+1,r,L,R,d);
39   c[rt]=max(c[rt*2],c[rt*2+1]);
40   s[rt]=s[rt*2]+s[rt*2+1];
41 }
42 lol query(int rt,int l,int r,int L,int R)
43 {
44   if (l>=L&&r<=R)
45     {
46       return s[rt];
47     }
48   int mid=(l+r)/2;
49   lol sum=0;
50   if (L<=mid) sum+=query(rt*2,l,mid,L,R);
51   if (R>mid) sum+=query(rt*2+1,mid+1,r,L,R);
52   return sum;
53 }
54 void change(int rt,int l,int r,int x,lol d)
55 {
56   if (l==r)
57     {
58       c[rt]=d;
59       s[rt]=d;
60       return;
61     }
62   int mid=(l+r)/2;
63   if (x<=mid) change(rt*2,l,mid,x,d);
64   else change(rt*2+1,mid+1,r,x,d);
65   c[rt]=max(c[rt*2],c[rt*2+1]);
66   s[rt]=s[rt*2]+s[rt*2+1];
67 }
68 int main()
69 {lol d;
70   int i,j,l,r,k;
71   cin>>n>>m;
72   for (i=1;i<=n;i++)
73     scanf("%lld",&a[i]);
74   build(1,1,n);
75   for (i=1;i<=m;i++)
76     {
77       scanf("%d",&opt);
78       if (opt==1)
79     {
80       scanf("%d%d",&l,&r);
81       printf("%lld\n",query(1,1,n,l,r));
82     }
83       else if (opt==2)
84     {
85       scanf("%d%d%lld",&l,&r,&d);
86       update(1,1,n,l,r,d);
87     }
88       else if (opt==3)
89     {
90       scanf("%d%lld",&k,&d);
91       change(1,1,n,k,d);
92     }
93     }
94 }

 

posted @ 2017-11-06 14:48  Z-Y-Y-S  阅读(318)  评论(0编辑  收藏  举报