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 线段树

CF438D The Child and Sequence(线段树)

CF438D The Child and Sequence