zoukankan      html  css  js  c++  java
  • FZU 2105 Digits Count(线段树)

    Problem 2105 Digits Count
    Accept: 302 Submit: 1477
    Time Limit: 10000 mSec Memory Limit : 262144 KB
    Problem Description

    Given N integers A={A[0],A[1],…,A[N-1]}. Here we have some operations:

    Operation 1: AND opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] AND opn (here “AND” is bitwise operation).

    Operation 2: OR opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] OR opn (here “OR” is bitwise operation).

    Operation 3: XOR opn L R

    Here opn, L and R are integers.

    For L≤i≤R, we do A[i]=A[i] XOR opn (here “XOR” is bitwise operation).

    Operation 4: SUM L R

    We want to know the result of A[L]+A[L+1]+…+A[R].

    Now can you solve this easy problem?
    Input

    The first line of the input contains an integer T, indicating the number of test cases. (T≤100)

    Then T cases, for any case, the first line has two integers n and m (1≤n≤1,000,000, 1≤m≤100,000), indicating the number of elements in A and the number of operations.

    Then one line follows n integers A[0], A[1], …, A[n-1] (0≤A[i]<16,0≤in).

    Then m lines, each line must be one of the 4 operations above. (0≤opn≤15)
    Output
    For each test case and for each “SUM” operation, please output the result with a single line.
    Sample Input
    1
    4 4
    1 2 4 7
    SUM 0 2
    XOR 5 0 0
    OR 6 0 3
    SUM 0 2
    Sample Output
    7
    18
    Hint

    A = [1 2 4 7]

    SUM 0 2, result=1+2+4=7;

    XOR 5 0 0, A=[4 2 4 7];

    OR 6 0 3, A=[6 6 6 7];

    SUM 0 2, result=6+6+6=18.
    由于数据特别多,但是数据的值不大(<16),所以必有大量重复的元素就可以进行区间合并

    #include <set>
    #include <map>
    #include <list>
    #include <stack>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define PI cos(-1.0)
    #define RR freopen("input.txt","r",stdin)
    using namespace std;
    typedef long long LL;
    const int MAX = 1000010;
    int Seg[MAX*6];
    int Arr[MAX];
    int n,m;
    int Oper(int num,int PN,int OP)//进行操作
    {
        switch(OP)
        {
        case 1:
            return num&PN;
        case 2:
            return num|PN;
        case 3:
            return num^PN;
        }
        return 0;
    }
    
    void Build(int L,int R,int site)//建立线段树
    {
        if(L==R)
        {
            Seg[site]=Arr[L];
            return ;
        }
        int mid=(L+R)>>1;
        Build(L,mid,site<<1);
        Build(mid+1,R,site<<1|1);
        if(Seg[site<<1]==Seg[site<<1|1]&&Seg[site<<1]!=1)//将值相同的区间进行合并,如果不相同则为-1.
        {
            Seg[site]=Seg[site<<1];
        }
        else
        {
            Seg[site]=-1;
        }
    }
    void Update(int L,int R,int l,int r,int site,int PN,int OP)//更新操作
    {
        if(L==l&&R==r&&Seg[site]!=-1)//三种操作
        {
            Seg[site]=Oper(Seg[site],PN,OP);
            return ;
        }
        int mid = (L+R)>>1;
        if(Seg[site]!=-1)//向下更新,如过对已经合并的区间里面进行操作,则需要将区间先拆分,更行完以后再判断是否可以合并
        {
            Seg[site<<1]=Seg[site<<1|1]=Seg[site];
            Seg[site]=-1;
        }
        if(r<=mid)
        {
            Update(L,mid,l,r,site<<1,PN,OP);
        }
        else if(l>mid)
        {
            Update(mid+1,R,l,r,site<<1|1,PN,OP);
        }
        else
        {
            Update(L,mid,l,mid,site<<1,PN,OP);
            Update(mid+1,R,mid+1,r,site<<1|1,PN,OP);
        }
        if(Seg[site<<1]==Seg[site<<1|1]&&Seg[site<<1]!=1)//区间合并
        {
            Seg[site]=Seg[site<<1];
        }
    }
    int Query(int L,int R,int l,int r,int site)//查询
    {
        if(L==l&&R==r&&Seg[site]!=-1)
        {
            return (R-L+1)*Seg[site];
        }
        if(Seg[site]!=-1)//查询的时候,如果要查询一个区间内的区间,则需要先将区间向下更新(想想为什么?);
        {
            Seg[site<<1]=Seg[site<<1|1]=Seg[site];
            Seg[site]=-1;
        }
        int mid=(L+R)>>1;
        if(r<=mid)
        {
            return Query(L,mid,l,r,site<<1);
        }
        else if(l>mid)
        {
            return Query(mid+1,R,l,r,site<<1|1);
        }
        else
        {
            return Query(L,mid,l,mid,site<<1)+Query(mid+1,R,mid+1,r,site<<1|1);
        }
    }
    int main()
    {
        int T;
        char str[15];
        int l,r,PN;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&n,&m);
            for(int i=0;i<n;i++)
            {
                scanf("%d",&Arr[i]);
            }
            Build(0,n-1,1);
            for(int i=1;i<=m;i++)
            {
                scanf("%s",str);
                if(strcmp(str,"SUM")==0)
                {
                    scanf("%d %d",&l,&r);
                    printf("%d
    ",Query(0,n-1,l,r,1));
                }
                else
                {
                    scanf("%d %d %d",&PN,&l,&r);
                    if(strcmp(str,"AND")==0)
                    {
                        Update(0,n-1,l,r,1,PN,1);
                    }
                    else if(strcmp(str,"OR")==0)
                    {
                        Update(0,n-1,l,r,1,PN,2);
                    }
                    else if(strcmp(str,"XOR")==0)
                    {
                        Update(0,n-1,l,r,1,PN,3);
                    }
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    存储器的分配与回收算法实现
    jsoup抓取借书记录
    java学习碰到死胡同了
    PHP MYSQL登陆和模糊查询
    JAVA进阶之路(一)
    String是最基本的数据类型吗?
    面向对象的特征有哪些方面
    sqoop
    你真的理解 new 了吗?
    面试题目 字符串的去重与压缩(统计)
  • 原文地址:https://www.cnblogs.com/juechen/p/5255945.html
Copyright © 2011-2022 走看看