题意:
一个序列,三种操作
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){  //subupdate_pos(1,1,n,x,y);}else{update_sec(1,1,n,x,y);}}}
}

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

  1. 2021HDU多校8 - 7059 Counting Stars(线段树)

    题目链接:点击查看 题目大意:给出 nnn 个数字,需要执行 mmm 次操作,每次操作分为下列三种类型: 1 l r :输出区间 [l,r][l,r][l,r] 的 sumsumsum 和 2 l r ...

  2. POJ 2352 Stars (线段树)

    POJ 2352 Stars (线段树) 手动博客搬家:本文发表于20170819 22:11:49, 原地址https://blog.csdn.net/suncongbo/article/detai ...

  3. 线段树模板题3:区间染色问题

    1.3线段树模板题3:区间染色问题 在DotA游戏中,帕吉的肉钩实际上是大多数英雄中最恐怖的东西.挂钩由长度相同的几个连续的金属棍组成. 现在,帕吉(Pudge)希望对挂接进行一些操作. 让我们将钩子 ...

  4. 环鸽的数列(数列的通项,区间加等比数列,区间求和)

    https://ac.nowcoder.com/acm/contest/5759/B 题意: 有一个递推数列  , 对于一个长度为  的区间,共有  次操作,每个操作给三个数字 ,你需要支持下面两种操 ...

  5. szu 寒训个人复习第一天 线段树入门单点修改,区间修改,以及线段树的扩展运用[线段树+dp][区间最大公约数]

    寒讯内容有点过多(其实是我太菜了)水一波怕忘了(人老了)**什么是线段树** 线段树是本蒟蒻感觉用处特别大的算法 那么线段树上面的节点表示什么意思呢? 线段树,上面的节点表示一个区间,父亲节点表示的区 ...

  6. poj 2352 Stars 线段树(先建后查/边建边查)/树状数组三种方法思路详解,带你深入了解线段树难度⭐⭐⭐★

    poj 2352 Stars 目录 poj 2352 Stars 1.树状数组 2.线段树,先建树后查找 3.线段树,边建树边查找 Description Astronomers often exam ...

  7. 线段树之延时标记(区间修改)及lazy思想

    暴力求解 1.最简单的方法是:在主函数中添加一个循环  进行 r-l+1次单点修改实现区间修改,对于单个元素修改时间复杂度为 O(log2(n)) 所以对于单个区间修改的时间复杂度为 O(n*log( ...

  8. NOI2016区间bzoj4653(线段树,尺取法,区间离散化)

    题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间,使得这 \(M\) 个区间共同包含至少一个 ...

  9. NYOJ 1068 ST(线段树之 成段更新+区间求和)

    ST 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 "麻雀"lengdan用随机数生成了后台数据,但是笨笨的他被妹纸的问题给难住了... 已知len ...

最新文章

  1. c如何正常中断一个运行的线程
  2. 另类×××应用(三):不花一分钱,实现总部和多分支机构网络互联
  3. MySQL跑在CentOS 6 和 7上的性能比较
  4. 转载:缓存 Cache
  5. 如何格式化电脑_移动硬盘提示格式化如何解决?数据恢复软件解决问题
  6. event类型 php,深入解析PHP的Laravel框架中的event事件操作
  7. 关于 Object.prototype.toString.call() 方法
  8. 大数据开发笔记(五):Zookeeper
  9. mysql:Error while performing database loggin with the mysql driver
  10. 极光推送 简书android,极光推送 (具体步骤,指导操作,推送成功)
  11. MSP430 单片机 读取 程序 LM75A LM75 温度传感器
  12. c语言万年历方案论证,C语言编写方案-万年历分析.doc
  13. 如何用计算机测量图片景深,用比较仔细的测量搞清楚“景深”(1.实测景深与公式比较)...
  14. Proof Compression
  15. c语言switch顺序,switch-case的执行顺序,该怎么处理
  16. 博客发在oschina
  17. Linux 云服务器的使用
  18. java接口 运动员,JAVA面向对象进阶实例【教练和运动员日常安排】
  19. python数据类型(一)
  20. 探索Android 9.0 Pie新特性变更

热门文章

  1. 解决response响应乱码
  2. OpenCV实现0到9数字识别OCR
  3. APS:大型多模态室内摄像机定位系统
  4. 【OpenCV 4开发详解】图像透视变换
  5. IAsyncResult接口
  6. 前后端分离后的前端时代
  7. vue 数据绑定实现的核心 Object.defineProperty()
  8. onCompositionStart与compositionend
  9. UVA 10306 e-Coins(全然背包: 二维限制条件)
  10. c++成员函数的调用