HDU7059-Counting Stars 线段树 (区间加最低位置,区间减最高位)

Posted 昵称很长很长真是太好了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU7059-Counting Stars 线段树 (区间加最低位置,区间减最高位)相关的知识,希望对你有一定的参考价值。

题意:
一个序列,三种操作
1.查询序列l,r之间的和
2.给l,r之间每个数加上自己二进制最高位
3.给l,r之间每个数减去自己二进制的最低位置。

题解:
我们把一个数分解成二进制的状态进行思考,设cnt为数x当前二进制状态下不为0的位数有多少,我们发现对于两个修改操作,你无论怎么修改,cnt都不会增加,考虑1e9最多有30位不为1的数,你每进行一次操作3,这个数的cnt就会-1,那么每个数最多可以进行30次操作三,多余的操作三没有什么效果。
我们可以把一个数分成(最高位+其他位)来进行维护。
那么对于操作3来讲,我们直接去暴力操作即可(暴力修改每个叶子结点,当一段区间最高位+次高位等于0时,就不需要递归下去了)
如果其他位不为0,那么直接用其他位-lowbit(其他位),如果为0,那么直接把最高位置为0即可。
操作2进行正常的区间修改。

操作三我们直接对最高位乘2(区间修改),其他位不变。

代码:

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>
#define endl '\\n'
using namespace std;

const int maxn=1e5+10;

int a[maxn];

inline char nc() 
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;

inline void read(int &sum) 
    char ch = nc();
    int tf = 0;
    sum = 0;
    while((ch < '0' || ch > '9') && (ch != '-')) ch = nc();
    tf = ((ch == '-') && (ch = nc()));
    while(ch >= '0' && ch <= '9') sum = sum * 10+ (ch - 48), ch = nc();
    (tf) && (sum =- sum);

inline void write(int x)
    if (x < 0) x = ~x + 1, putchar('-');
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');

const int mod=998244353;

long long maxsum[maxn<<2],lowsum[maxn<<2];
int bit[maxn+100],lazy[maxn<<2],b[maxn<<2];
bool maxsumbit[maxn<<2];
void push_up(int node)
    lowsum[node]=(lowsum[node<<1]+lowsum[node<<1|1])%mod;
    maxsum[node]=(maxsum[node<<1]+maxsum[node<<1|1])%mod;
    if(!maxsumbit[node<<1]&&!maxsumbit[node<<1|1]) maxsumbit[node]=false;
    else maxsumbit[node]=true;


void push_down(int node)
    if(lazy[node])
        lazy[node<<1]+=lazy[node];
        lazy[node<<1|1]+=lazy[node];
        maxsum[node<<1]=(maxsum[node<<1]*bit[lazy[node]])%mod;
        maxsum[node<<1|1]=(maxsum[node<<1|1]*bit[lazy[node]])%mod;
        lazy[node]=0;
    


void build(int node,int start,int ends)
    lazy[node]=0;
    if(start==ends)
        if(b[start]==-1) maxsumbit[node]=false;
        else maxsumbit[node]=true;

        lowsum[node]=a[start]%mod;
        if(b[start]!=-1) maxsum[node]=bit[b[start]];
        else maxsum[node]=0;
        return ;
    
    int mid=(start+ends)>>1;
    build(node<<1,start,mid);
    build(node<<1|1,mid+1,ends);
    push_up(node);


void update_pos(int node,int start,int ends,int l,int r)
    if(!maxsumbit[node]) return ;
    if(start==ends)
        if(lowsum[node]==0)
            maxsum[node]=0;
            maxsumbit[node]=false;
        
        else lowsum[node]=(lowsum[node]-(lowsum[node]&(-lowsum[node]))+mod)%mod;
        return ;
    
    push_down(node);
    int mid=(start+ends)>>1;
    if(l<=mid) update_pos(node<<1,start,mid,l,r);
    if(mid<r) update_pos(node<<1|1,mid+1,ends,l,r);
    push_up(node);

void update_sec(int node,int start,int ends,int l,int r)

    if(!maxsumbit[node]) return;
    if(l<=start&&ends<=r)
        maxsum[node]=(maxsum[node]*2)%mod;
        lazy[node]++;
        return ;
    
    push_down(node);
    int mid=(start+ends)>>1;
    if(l<=mid) update_sec(node<<1,start,mid,l,r);
    if(mid<r) update_sec(node<<1|1,mid+1,ends,l,r);
    push_up(node);


long long query(int node,int start,int ends,int l,int r)
    if(l<=start&&ends<=r)
        return (lowsum[node]+maxsum[node])%mod;
    
    int mid=(start+ends)>>1;
    push_down(node);
    long long res=0;
    if(l<=mid) res=(res+query(node<<1,start,mid,l,r));
    if(mid<r) res=(res+query(node<<1|1,mid+1,ends,l,r));
    return res;


signed main()
    bit[0]=1;
    for(int i=1;i<=100100;i++)
        bit[i]=(bit[i-1]*2)%mod;
    
    int t;
    read(t);
    while(t--)
        int n;
        read(n);
        for(int i=1;i<=n;i++)
            read(a[i]);
            b[i]=-1;
            for(int k=31;k>=0;k--)
                if((a[i]>>k&1)==1)
                    b[i]=k;
                    break;
                
            
            if(b[i]!=-1) a[i]-=bit[b[i]];
        
        build(1,1,n);
        int q;
        read(q);
        while(q--)
            int opt,x,y;
            read(opt);read(x);read(y);
            if(opt==1)
                int ans=(query(1,1,n,x,y)%mod+mod)%mod;
                write(ans);
                putchar('\\n');
            
            else if(opt==2)  //sub
                update_pos(1,1,n,x,y);
            
            else
                update_sec(1,1,n,x,y);
            
        

    


以上是关于HDU7059-Counting Stars 线段树 (区间加最低位置,区间减最高位)的主要内容,如果未能解决你的问题,请参考以下文章

HDU7059-Counting Stars 线段树 (区间加最低位置,区间减最高位)

HDOJ7059Counting Stars(线段树,区间加,乘,标记)

树状数组入门 hdu1541 Stars

POJ 2352 Stars(线段树)

POJ 2352 Stars (线段树)

POJ 2352 Stars 线段树