438D - The Child and Sequence
Posted dwvictor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了438D - The Child and Sequence相关的知识,希望对你有一定的参考价值。
#include <stdio.h>
#include <algorithm>
using namespace std;
#define lson num << 1
#define rson num << 1 | 1
#define MAXN 100005
typedef long long ll;
int a[MAXN << 1];
struct node
int l,r;
ll Max,sum;
tree[MAXN << 2];
void pushup(ll rt)
tree[rt].Max = max(tree[rt << 1].Max,tree[rt << 1|1].Max);
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1|1].sum;
// void build(int num,int l,int r)
//
// tree[num].l = l;
// tree[num].r = r;
// if(l == r)
// //scanf("%I64d",&tree[num].Max);
// tree[num].sum = tree[num].Max = a[l];
// return;
//
// int mid = (l + r) >> 1;
// build(lson,l,mid);
// build(rson,mid + 1,r);
// pushup(num);
//
void build(ll rt,ll l ,ll r)
tree[rt].l = l , tree[rt].r = r;
if(l == r)
tree[rt].sum = tree[rt].Max = a[l];
return;
ll mid = (l + r) >> 1;
build(rt << 1, l , mid);
build(rt <<1|1,mid + 1,r);
pushup(rt);
// ll query(int num,int l,int r)
//
// if(tree[num].l == l && tree[num].r == r)
// return tree[num].sum;
//
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(r <= mid)
// return query(lson,l,r);
//
// else if(l > mid)
// return query(rson,l,r);
//
// else
// return query(lson,l,mid) + query(rson,mid + 1,r);
//
//
ll query(ll rt,ll l,ll r)
if(tree[rt].l == l && r == tree[rt].r)
return tree[rt].sum;
//cout << rt << endl;
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(r <= mid) return query(rt << 1,l ,r);
else if(l > mid) return query(rt << 1|1,l,r);
else return query(rt << 1,l, mid) + query(rt << 1|1 , mid + 1, r);
// void update1(int num,int l,int r,int mod)
//
// if(tree[num].Max < mod)
// return;
//
// if(tree[num].l == tree[num].r)
// tree[num].Max %= mod;
// tree[num].sum %= mod;
// return;
//
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(r <= mid)
// update1(lson,l,r,mod);
//
// else if(l > mid)
// update1(rson,l,r,mod);
//
// else
// update1(lson,l,mid,mod),update1(rson,mid + 1,r,mod);
//
// pushup(num);
//
void update1(ll rt,ll l ,ll r ,ll v)
// cout << t[rt].maxx << endl;
if(v > tree[rt].Max) return;
if( tree[rt].l == tree[rt].r)
tree[rt].Max %= v; tree[rt].sum %= v;
// cout << t[rt].sum << " " << 111 << endl;
return;
//
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(r <= mid) update1(rt << 1,l ,r,v);
else if(l > mid) update1(rt << 1|1,l,r,v);
else update1(rt << 1,l, mid,v) , update1(rt << 1|1 , mid + 1, r,v);
pushup(rt);
// void update2(int num,int pos,int val)
//
// if(tree[num].l == tree[num].r && tree[num].l == pos)
// tree[num].sum = val;
// tree[num].Max = val;
// return;
//
// int mid = (tree[num].l + tree[num].r) >> 1;
// if(pos <= mid)
// update2(lson,pos,val);
//
// else
// update2(rson,pos,val);
//
// pushup(num);
//
void update2(ll rt,ll x,ll v)
if(tree[rt].l == tree[rt].r && tree[rt].l == x)
tree[rt].Max = tree[rt].sum = v;
return;
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if(x <= mid) update2(rt << 1,x , v);
else update2(rt << 1|1,x , v);
pushup(rt);
// int main(void)
//
// int n,m;
// scanf("%d%d",&n,&m);
// for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
// build(1,1,n);
// while(m--)
// int op,l,r,pos,x;
// scanf("%d",&op);
// if(op == 1)
// scanf("%d%d",&l,&r);
// printf("%I64d\n",query(1,l,r));
//
// else if(op == 2)
// scanf("%d%d%d",&l,&r,&x);
// update1(1,l,r,x);
//
// else
// scanf("%d%d",&pos,&x);
// update2(1,pos,x);
//
//
// return 0;
//
int main(int argc, char const *argv[])
ll n , m ;
scanf("%lld%lld",&n,&m);
for(ll i = 1;i <= n ; i++) scanf("%lld",&a[i]);
build(1,1,n);
//for(ll i = 1;i <= 40; i++) cout << t[i].sum << endl;
while(m--)
ll a;
scanf("%lld",&a);
if(a == 1)
ll b , c;
scanf("%lld%lld",&b,&c);
printf("%lld\n",query(1,b,c));
else if(a == 2)
ll b ,c, pos;
scanf("%lld%lld%lld",&b,&c,&pos);
update1(1,b,c,pos);
else
ll b , c;
scanf("%lld%lld",&b,&c);
update2(1,b,c);
return 0;
线段树重要思想
线段树单点修改的本质就是区间修改
本题是对所有数取模,如果对区间和取模,必定会影响子节点,那么便只能对子节点取模
但是如果一个一个取模,便会有超时的危险
那么我们就可以利用剪枝的思想,对小于mod的数/区间,直接返回
只对大于mod的数进行取模,那么便能降低复杂度。
#include <stdio.h>
#include <algorithm>
using namespace std;
#define lson num << 1
#define rson num << 1 | 1
#define MAXN 100005
typedef long long ll;
struct node
int l,r;
ll Max,sum;
tree[MAXN << 2];
void pushup(int num)
tree[num].Max = max(tree[lson].Max,tree[rson].Max);
tree[num].sum = tree[lson].sum + tree[rson].sum;
void build(int num,int l,int r)
tree[num].l = l;
tree[num].r = r;
if(l == r)
scanf("%I64d",&tree[num].Max);
tree[num].sum = tree[num].Max;
return;
int mid = (l + r) >> 1;
build(lson,l,mid);
build(rson,mid + 1,r);
pushup(num);
ll query(int num,int l,int r)
if(tree[num].l >= l && tree[num].r <= r)
return tree[num].sum;
int mid = (tree[num].l + tree[num].r) >> 1;
if(r <= mid)
return query(lson,l,r);
else if(l > mid)
return query(rson,l,r);
else
return query(lson,l,mid) + query(rson,mid + 1,r);
void update1(int num,int l,int r,int mod)
if(tree[num].Max < mod)
return;
//因为修改的是最大值,不是区间修改,所以是这个
if(tree[num].l == tree[num].r)
tree[num].Max %= mod;
tree[num].sum %= mod;
return;
int mid = (tree[num].l + tree[num].r) >> 1;
if(r <= mid)
update1(lson,l,r,mod);
else if(l > mid)
update1(rson,l,r,mod);
else
update1(lson,l,mid,mod),update1(rson,mid + 1,r,mod);
pushup(num);
void update2(int num,int pos,int val)
if(tree[num].l == tree[num].r )
tree[num].sum = val;
tree[num].Max = val;
return;
int mid = (tree[num].l + tree[num].r) >> 1;
if(pos <= mid)
update2(lson,pos,val);
else
update2(rson,pos,val);
pushup(num);
int main(void)
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
int op,l,r,pos,x;
scanf("%d",&op);
if(op == 1)
scanf("%d%d",&l,&r);
printf("%I64d\n",query(1,l,r));
else if(op == 2)
scanf("%d%d%d",&l,&r,&x);
update1(1,l,r,x);
else
scanf("%d%d",&pos,&x);
update2(1,pos,x);
return 0;
以上是关于438D - The Child and Sequence的主要内容,如果未能解决你的问题,请参考以下文章
CF(438D) The Child and Sequence(线段树)
Codeforces 438D The Child and Sequence
CodeForces 438D The Child and Sequence
CF438D The Child and Sequence 线段树