当前位置: 首页 > news >正文

A 找倍数 (线段树)

(“华讯杯”内蒙古自治区第十七届大学生程序设计竞赛 A题 找倍数)

题目描述

有一个下标从 1 到 n 的数列,需要进行 q 次操作。操作有两种类型:

  • 修改操作(类型1):将下标在区间 [l, r] 中的每一个数加上 x
    格式:1 l r x
  • 查询操作(类型2):求出下标在区间 [l, r] 内的数中有多少是 y 的倍数(保证 y 是 m 的因子)
    格式:2 l r y
输入格式:

第一行包含三个整数 n , q , m n, q, m n,q,m 1 ≤ n , q ≤ 100 , 000 , 1 ≤ m ≤ 50 1 \leq n, q \leq 100,000, 1 \leq m \leq 50 1n,q100,0001m50 ),分别表示数列长度、操作次数和常数 m m m

第二行包含 n n n 个用空格分隔的整数,表示数列的初始值 a i a_i ai 0 ≤ a i ≤ m 0 \leq a_i \leq m 0aim )。

接下来 q q q 行,每行描述一个操作:四个整数,第一个是操作类型(1 或 2),后三个是操作参数(含义如上)。

输出格式:

对于每个类型 2 的操作,输出一行整数,表示查询的结果。

输入样例:
5 6 10
1 2 4 6 8
2 1 5 2
1 1 5 1
2 3 5 2
2 1 3 2
1 5 5 1
2 1 5 10
输出样例:
4
0
1
1

思路

区间问题使用线段树维护:

m 的值不超过 50,因此因子 y 的取值只有少数几个。

每个线段树节点维护一个数组 cnt[MAXM],其中 cnt[i] 表示该节点对应区间内值 ≡ i (mod m) 的元素个数。

区间加法操作相当于对区间内所有数的模 m 结果进行平移((i + x) % m)。

查询时,直接累加所有 i ≡ 0 (mod y) 的 cnt[i] 值。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define pb push_back
#define pii pair<int, int>
#define FU(i, a, b) for (int i = (a); i <= (b); ++i)
#define FD(i, a, b) for (int i = (a); i >= (b); --i)
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 5, MAXN = maxn;
const int maxm = 50;
int n, m, q;
int a[maxn];
struct node {int lz = 0;int l, r;int cnt[maxm] = {};
} tr[4 * maxn];void pushup(int p) {for (int i = 0; i < maxm; i++) {tr[p].cnt[i] = tr[2 * p].cnt[i] + tr[2 * p + 1].cnt[i];}
}void apply(int p, int x) {x %= m;int tcnt[maxm] = {};for (int i = 0; i < m; i++) {int j = (i + x) % m;tcnt[j] += tr[p].cnt[i];}memcpy(tr[p].cnt, tcnt, sizeof(int) * m);tr[p].lz = (tr[p].lz + x) % m;
}void pushdown(int p) {if (tr[p].lz) {if (tr[p].l != tr[p].r) {apply(2 * p, tr[p].lz);apply(2 * p + 1, tr[p].lz);tr[p].lz = 0;}}
}void build(int p, int l, int r) {tr[p].l = l;tr[p].r = r;tr[p].lz = 0;memset(tr[p].cnt, 0, sizeof(tr[p].cnt));if (l == r) {tr[p].cnt[(a[l] % m)] = 1;return;}int mid = (l + r) / 2;build(2 * p, l, mid);build(2 * p + 1, mid + 1, r);pushup(p);
}void add(int p, int l, int r, int x) {if (x % m == 0)return;if (l <= tr[p].l && tr[p].r <= r) {apply(p, x);return;}pushdown(p);int mid = (tr[p].l + tr[p].r) / 2;if (mid >= l) {add(2 * p, l, r, x);}if (mid < r) {add(2 * p + 1, l, r, x);}pushup(p);
}int ask(int p, int l, int r, int y) {if (l <= tr[p].l && tr[p].r <= r) {int sum = 0;for (int i = 0; i < m; i += y) {sum += tr[p].cnt[i];}return sum;}pushdown(p);int mid = (tr[p].l + tr[p].r) / 2;int res = 0;if (mid >= l) {res += ask(2 * p, l, r, y);}if (mid < r) {res += ask(2 * p + 1, l, r, y);}return res;
}signed main() {
#ifndef ONLINE_JUDGEfreopen("../in.txt", "r", stdin);
#endifcin.tie(0)->ios::sync_with_stdio(0);cin >> n >> q >> m;FU(i, 1, n) { cin >> a[i]; }build(1, 1, n);while (q--) {int op, l, r, y;cin >> op >> l >> r >> y;if (op == 1) {add(1, l, r, y);} else {cout << ask(1, l, r, y) << endl;}}return 0;
}

相关文章:

  • 嵌入式学习笔记DAY35(数据库)
  • 龙虎榜——20250610
  • 算法题(166):占卜DIY
  • Zustand 状态管理库:极简而强大的解决方案
  • 城市照明深夜全亮太浪费?智能分时调光方案落地贵州某市
  • 精读 2025 《可信数据空间标准体系建设指南》【附全文阅读】
  • ​​扩散模型调度器(Scheduler)
  • MySQL事务——博主总结
  • pycharm最近遇到的一些问题
  • 理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
  • rapidocr v3.1.0发布
  • HDFS 3.4.1 集成Kerberos 实现账户认证
  • 6月10日星期二今日早报简报微语报早读
  • 用纯.NET开发并制作一个智能桌面机器人(五):使用.NET为树莓派开发Wifi配网功能
  • Unit 2 训练你的第一个深度强化学习智能体 LunarLander-v3
  • 慢接口优化万能公式-适合所有系统
  • 1.2 git使用
  • SIP协议之NACK(Negative Acknowledgement)
  • LLMs 系列实操科普(3)
  • 智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
  • 提升网站权重/怎样做自己的网站
  • 建设网站的程序/如何设计企业网站
  • 网站app开发流程/软文500字范文
  • 上海集团网站建设/重庆专业seo
  • wordpress 付费内容/温州seo推广外包
  • 网站做的支付宝接口/app安装下载