码迷,mamicode.com
首页 > 其他好文 > 详细

438D - The Child and Sequence

时间:2019-07-17 00:07:23      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:turn   using   lld   本质   一个   nod   upd   child   name   

 

 

 

#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

标签:turn   using   lld   本质   一个   nod   upd   child   name   

原文地址:https://www.cnblogs.com/DWVictor/p/11198271.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!