zoukankan      html  css  js  c++  java
  • SPOJ MULTQ3 7299 Multiples of 3 (区间更新)

     题目连接:http://www.spoj.com/problems/MULTQ3/

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #define lson rt<<1,L,mid
    #define rson rt<<1|1,mid+1,R
    /*
    题意:给出n个数,初试为0,给出两个操作;
        0 A B :将[A,B]区间中的每个数+1
        1 A B :询问[A,B]区间中有多少个能被3整除的数。
    思路:每个节点存储三个值:num0:整除3的个数,num1:除以3余1的个数,num2:除以3余2的个数
          更新的时候,只要将这三个值互换即可
    */
    using namespace std;
    const int maxn=100005;
    int n,m;
    
    struct Node{
        //num0:整除3的个数,num1:除以3余1的个数,num2:除以3余2的个数
        int num0,num1,num2;
        int lazy;  //标记该区间+1的次数,如果三次+1相当于不变
    }tree[maxn<<2];
    
    void build(int rt,int L,int R){
        tree[rt].num0=(R-L+1);
        tree[rt].num1=tree[rt].num2=0;
        tree[rt].lazy=0;
        if(L==R)
            return;
        int mid=(R+L)>>1;
        build(lson);
        build(rson);
    }
    void pushUp(int rt){
        tree[rt].num0=tree[rt<<1].num0+tree[rt<<1|1].num0;
        tree[rt].num1=tree[rt<<1].num1+tree[rt<<1|1].num1;
        tree[rt].num2=tree[rt<<1].num2+tree[rt<<1|1].num2;
    }
    void pushDown(Node &rt,Node &ls,Node &rs){
        if(rt.lazy==1){
            /*
            +1一次:
            num0->num1
            num1->num2
            num2->num0
            */
            int tmp;
            tmp=ls.num0;
            ls.num0=ls.num2;
            ls.num2=ls.num1;
            ls.num1=tmp;
            ls.lazy=(ls.lazy+rt.lazy)%3;
    
            tmp=rs.num0;
            rs.num0=rs.num2;
            rs.num2=rs.num1;
            rs.num1=tmp;
            rs.lazy=(rs.lazy+rt.lazy)%3;
    
            rt.lazy=0;
        }
        else if(rt.lazy==2){
            /*
            +1二次:
            num0->num2
            num2->num1
            num1->num0
            */
            int tmp;
            tmp=ls.num0;
            ls.num0=ls.num1;
            ls.num1=ls.num2;
            ls.num2=tmp;
            ls.lazy=(ls.lazy+rt.lazy)%3;
    
            tmp=rs.num0;
            rs.num0=rs.num1;
            rs.num1=rs.num2;
            rs.num2=tmp;
            rs.lazy=(rs.lazy+rt.lazy)%3;
            rt.lazy=0;
        }
    }
    void update(int rt,int L,int R,int l,int r){
        if(l<=L&&R<=r){
            int tmp;
            tmp=tree[rt].num0;
            tree[rt].num0=tree[rt].num2;
            tree[rt].num2=tree[rt].num1;
            tree[rt].num1=tmp;
            tree[rt].lazy=(tree[rt].lazy+1)%3;
            return;
        }
        pushDown(tree[rt],tree[rt<<1],tree[rt<<1|1]);
        int mid=(L+R)>>1;
        if(l<=mid)
            update(lson,l,r);
        if(r>mid)
            update(rson,l,r);
        pushUp(rt);
    }
    int query(int rt,int L,int R,int l,int r){
        if(l<=L&&R<=r){
            return tree[rt].num0;
        }
        pushDown(tree[rt],tree[rt<<1],tree[rt<<1|1]);
        int ret=0;
        int mid=(L+R)>>1;
        if(l<=mid)
            ret+=query(lson,l,r);
        if(r>mid)
            ret+=query(rson,l,r);
        return ret;
    }
    int main()
    {
        int t,a,b;
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&t,&a,&b);
            a++;b++;
            if(t==0){
                update(1,1,n,a,b);
            }
            else{
                int ans=query(1,1,n,a,b);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    Vimdiff的用法 简单
    VIM插件使用 简单
    张子阳:大道至简,职场上做人做事做管理 简单
    VIM常用快捷键整理 简单
    从程序员到项目经理(四):外行可以领导内行吗 简单
    从程序员到项目经理(三):认识项目经理 简单
    余波:技术人员如何走出职业迷茫 简单
    技术路线的选择重要但不具有决定性 简单
    转:我在Facebook工作的十大经验分享 简单
    linux下vim的编译以及终端乱码的解决方案 简单
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3418459.html
Copyright © 2011-2022 走看看