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;
    }
    
  • 相关阅读:
    PAT顶级 1015 Letter-moving Game (35分)
    PAT顶级 1008 Airline Routes (35分)(有向图的强连通分量)
    PAT顶级 1025 Keep at Most 100 Characters (35分)
    PAT顶级 1027 Larry and Inversions (35分)(树状数组)
    PAT 顶级 1026 String of Colorful Beads (35分)(尺取法)
    PAT顶级 1009 Triple Inversions (35分)(树状数组)
    Codeforces 1283F DIY Garland
    Codeforces Round #438 A. Bark to Unlock
    Codeforces Round #437 E. Buy Low Sell High
    Codeforces Round #437 C. Ordering Pizza
  • 原文地址:https://www.cnblogs.com/juechen/p/5255945.html
Copyright © 2011-2022 走看看