D - Counting Stars HDU - 7059

题解:

长度为n的序列a,有三个操作:

  1. 对某个区间进行询问
  2. 对于某个区间内的每个数ai,减去ai&(-ai)
  3. 对于某个区间内的每个数ai,加上2k2^k2k,k满足2k<=ai<2k+12^k <= a_{i} <2^{k+1}2k<=ai​<2k+1

题解:

很容易想到线段树维护,但是后两个操作都不是线段树的基础操作
对于第二个操作,如何维护,其实线段树问题中经常遇到,对于这种数值快速递降至稳定的函数(比如区间开根号,区间求欧拉函数),可以直接暴力修改。像本题中是减去lowbit(x),其实就是将x二进制中的最后一位1删除,那每个数最多也就操作个log x次就变成0,因此一共操作次数只有nlogn次,再加上线段树操作的复杂度,也就是O(nlog2n)O(nlog^2n)O(nlog2n)
对于第三个操作,加上2k2^k2k,k满足2k<=ai<2k+12^k <= a_{i} <2^{k+1}2k<=ai​<2k+1,其实本质就是让ai的最左边的1左移一位。也就是说其实第三个操作只与ai的最高位有关,且是乘2,乘2这个操作是可以用线段树实现的。
具体实现就是:我们将ai的最高位和剩余位置拆开,sum1记录的是最高位的情况,sum2记录是剩余最高位情况,num记录ai中1的情况,因为操作2是要减去最后一位1,如果num==0,那么sum1和sum2就都等于0。对于操作2,让sum2-=lowbit(sum2),对于操作3,只需要对sum2进行乘2的维护。查询时再将sum1和sum2加在一起

代码:

详细看代码

// Problem: D - Counting Stars
// Contest: Virtual Judge - 2021杭电多校第八场
// URL: https://vjudge.net/contest/453140#problem/D
// Memory Limit: 131 MB
// Time Limit: 4000 ms
// Data:2021-08-13 12:59:28
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int mod= 998244353;
const int maxn= 2e5 + 9;
int a[maxn];
int pw[maxn];
struct node
{int l, r;ll sum1; //记录最高位的1ll sum2; //记录除了最高位剩下的ll num; //记录二进制一共有几个1ll lazy; //记录乘2的标记
} tr[maxn << 2];
int lg[maxn]; //lg[i]表示a[i]的二进制有几位
int work(int x)
{ //计算x的二进制有几位int ans= 0;while (x) {ans++;x>>= 1;}return ans;
}
int work2(int x)
{ //计算x的二进制有几位是1int ans= 0;while (x) {if (x & 1)ans++;x>>= 1;}return ans;
}
int lowbit(int x)
{return x & (-x);
}
void pushup(int rt)
{tr[rt].sum1= (tr[rt << 1].sum1 + tr[rt << 1 | 1].sum1) % mod;tr[rt].sum2= (tr[rt << 1].sum2 + tr[rt << 1 | 1].sum2) % mod;tr[rt].num= max(tr[rt << 1].num, tr[rt << 1 | 1].num);
}
void solve(int rt, int val)
{tr[rt].sum1= 1ll * tr[rt].sum1 * pw[val] % mod;tr[rt].lazy+= val;
}
void pushdown(int rt)
{solve(rt << 1, tr[rt].lazy);solve(rt << 1 | 1, tr[rt].lazy);tr[rt].lazy= 0;
}
void build(int rt, int l, int r)
{tr[rt].l= l;tr[rt].r= r;tr[rt].lazy= 0;if (l == r) {tr[rt].num= work2(a[l]);tr[rt].sum1= (a[l] & (1 << (lg[l] - 1)));tr[rt].sum2= a[l] - tr[rt].sum1;return;}int mid= (l + r) >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);pushup(rt);
}
void update1(int rt, int l, int r)
{if (tr[rt].num == 0)return;if (tr[rt].l > r || tr[rt].r < l)return;if (tr[rt].l == tr[rt].r) {tr[rt].sum2= tr[rt].sum2 - lowbit(tr[rt].sum2);tr[rt].num--;if (tr[rt].num == 0) { //全减没了tr[rt].sum1= 0;tr[rt].sum2= 0;}return;}pushdown(rt);int mid= (tr[rt].l + tr[rt].r) >> 1;if (l <= mid)update1(rt << 1, l, r);if (r > mid)update1(rt << 1 | 1, l, r);pushup(rt);
}
void update2(int rt, int l, int r)
{if (tr[rt].l > r || tr[rt].r < l)return;if (tr[rt].l >= l && tr[rt].r <= r) {solve(rt, 1);return;}pushdown(rt);int mid= (tr[rt].l + tr[rt].r) >> 1;if (l <= mid)update2(rt << 1, l, r);if (r > mid)update2(rt << 1 | 1, l, r);pushup(rt);
}
ll query(int rt, int l, int r)
{if (tr[rt].l > r || tr[rt].r < l)return 0;if (tr[rt].l >= l && tr[rt].r <= r) {return (1ll * tr[rt].sum1 + tr[rt].sum2) % mod;}pushdown(rt);int mid= (tr[rt].l + tr[rt].r) >> 1;ll ans= 0;if (l <= mid)ans= (ans + query(rt << 1, l, r)) % mod;if (r > mid)ans= (ans + query(rt << 1 | 1, l, r)) % mod;return ans % mod;
}
int main()
{//rd_test();int t;pw[0]= 1;for (int i= 1; i < 200004; i++)pw[i]= 1ll * pw[i - 1] * 2 % mod;scanf("%d", &t);while (t--) {int n;scanf("%d", &n);for (int i= 1; i <= n; i++) {scanf("%d", &a[i]);lg[i]= work(a[i]);}//memset(tr,0,sizeof(tr));build(1, 1, n);int m;read(m);for (int i= 1; i <= m; i++) {int op, l, r;scanf("%d%d%d", &op, &l, &r);if (op == 1)printf("%d\n", query(1, l, r));else if (op == 2)update1(1, l, r);else if (op == 3)update2(1, l, r);}}return 0;//Time_test();
}

D - Counting Stars HDU - 7059相关推荐

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

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

  2. 【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)

    题干: Little A is an astronomy lover, and he has found that the sky was so beautiful! So he is countin ...

  3. E - Counting Cliques HDU - 5952

    E - Counting Cliques HDU - 5952 题意: 给你n个点,m个边,还有一个s,问这个图中有多少个等于s的点集可以组成一个完全图 题解: 这题..直接暴力搜索就行 分析复杂度的 ...

  4. 【HDOJ7059】Counting Stars(线段树,区间加,乘,标记)

    1004 Counting Stars 题意: 给出一个长为n的序列(1e5),支持3种操作: 1:查询[l,r]的区间和 2:修改[l,r]中每个数,都减去lowbit(x) 3:修改[l,r]中每 ...

  5. HDU - 6184 Counting Stars(思维+三元环)

    题目链接:点击查看 题目大意:给出一个 nnn 个点 mmm 条边组成的无向图,问图中有多少个"三元环对","三元环对"指的是两个三元环共用了一条边 题目分析: ...

  6. HDU 6184 2017广西邀请赛:Counting Stars(三元环)

    题意: n个点m条边的无向图,问有多少个A-structure 其中A-structure满足V=(A,B,C,D) && E=(AB,BC,CD,DA,AC) 可以看出A-struc ...

  7. Counting Intersections HDU - 5862

    http://acm.hdu.edu.cn/showproblem.php?pid=5862 将竖线(y1 y2 x)拆为两个点 分别在y1 y2+1高度更新x位置 x轴用线段树维护 对于横线(x1 ...

  8. Counting Divisors HDU - 6069

    设n=p_1^{c_1}p_2^{c_2}...p_m^{c_m}n=p​1​c​1​​​​p​2​c​2​​​​...p​m​c​m​​​​,则d(n^k)=(kc_1+1)(kc_2+1)...( ...

  9. Stars HDU 1541

    题意:每个星星有一个等级,该等级为它左下角的星星的个数.星星的坐标按Y坐标为第一关键字X坐标为第二关键字的递增的顺序给出.最后输出0~n-1等级的星星一共有多少个. 题解:树状数组. AC代码: Vi ...

最新文章

  1. Java的File类
  2. Java中的异常处理
  3. 我为什么更喜欢 Mac OS X
  4. JavaSE学习53:细说多线程之内存可见性
  5. SpringMVC处理MYSQL BLOB字段的上传
  6. docker安装、启动mongo
  7. Android-service
  8. MongoDB最简单的入门教程之二 使用nodejs访问MongoDB
  9. signature=54cb1c123491dc1a268a21f3502cccfc,Modelling information routing with noninterference
  10. docker jdk mysql_docker部署springboot前后端分离项目(jdk+jar包+mysql+redis+nginx)(示例代码)...
  11. java 栈 大小_java – JVM堆栈大小规范
  12. 酷派起诉小米:你竟敢侵我的权?
  13. 报表中去除字符中的空格
  14. IDEA下SSM项目搭建的基本操作
  15. 再说一次,别去外包!
  16. Linux内存管理之vmalloc与low_memory
  17. Python下载Wyoming怀俄明大学探空数据(数据网址更新)
  18. 实时交通仿真平台概要
  19. LabVIEW:忽略自动错误处理
  20. Python画四张子图-导入数据

热门文章

  1. 博古通今的孩子是怎么养成的?答案就在这本影响了无数中国人思想的奇书里……
  2. 马斯克又要搞事情,不锈钢材质的Space X“星际飞船”正式亮相
  3. 快速成长为数据挖掘高手的秘诀
  4. 《SAS编程与数据挖掘商业案例》学习笔记之一
  5. angular的html引入js,在AngularJS中的文件夹中加载JavaScript和CSS文件
  6. python地理空间分析指南pdf邓世超_Python地理空间分析指南(第2版)源代码.zip
  7. c语言哈密顿路径算法,用于检查给定图中是否存在哈密顿循环或路径的C ++程序...
  8. 2020年python2停止更新_Python核心团队计划2020年停止支持Python2,NumPy宣布停止支持计划表...
  9. oracle数据缓冲区作用,Oracle内存结构(02)--缓冲区
  10. mysql update返回_MySQL中,当update修改数据与原数据相同时会再次执行吗?