ZOJ 3940 Modulo Query(优先队列)
来源:互联网 发布:怎样加入淘宝客推广 编辑:程序博客网 时间:2024/06/04 01:31
省赛题解:http://async.icpc-camp.org/d/405-2016
E. MODULO QUERY
可以观察到一个区间对一个数取模后的结果也可以用区间来表示,并且这些区间的左端点都是0。于是直接用一个map存每次取模之后的区间和这个区间出现次数,要取模的时候,找出所有右端点大于等于当前模数的所有区间,暴力算一下结果即可。对于查询,二分下位置,求个后缀和就好了。下面分析下复杂度为什么是对的。
众所周知:一个数对一堆数取模,最多会有log
次值的改变。对于这题每对一个新数取模,最多只会增加一个区间。考虑当前区间是[0,vi]
,要对x
取模,那么对于vi<x
的区间没有变化,对于vi≥x
的那些区间会变成[0,vi mod x]
,并且可能会新增区间[0,x−1]
。这个过程其实相当于每个ai
对后面所有数依次取模,那么总共会有O(nlogn)
次值的改变,每次改变需要在map上修改一下,总复杂度是O(nlog2n)
的。
//题意:自行理解#include <iostream>#include <string.h>#include <queue>#include <climits>#include <algorithm>using namespace std;#define maxn 500005const int mod = 1e9+7;int sum[maxn];int ans[maxn];struct node{ // 区间[0, right]以及该区间出现的次数cnt int right, cnt; node(int a = 0, int b = 0) { right = a, cnt = b; } bool operator<(const node &a) const { return right < a.right; }}tp[100005];int main(){ int t; cin>>t; while(t--) { int n, m, s; cin>>n>>m; priority_queue<node> que; //优先队列 que.push(node(m, 1)); //入队 while(n--) { cin>>s; while(que.top().right >= s) //将区间右断点大于s的区间进行mod处理 { node tmp = que.top(); que.pop(); while(!que.empty() && que.top().right == tmp.right) //如果有重复的区间进行整合 tmp.cnt += que.top().cnt, que.pop(); que.push(node(s - 1, (tmp.right + 1)/ s * tmp.cnt)); //将处理过后的区间入队 if((tmp.right + 1)% s) que.push(node(tmp.right%s, tmp.cnt)); //如果一个区间不能被整除 将多余的区间入队 } } int cnt = 1; while(!que.empty()) //将最后得到的所有区间存在一个数组中 { node tmp = que.top(); que.pop(); while(!que.empty() && que.top().right == tmp.right) tmp.cnt += que.top().cnt, que.pop(); tp[cnt++] = tmp; } sort(tp + 1, tp + cnt); //将各个区间进行从小到大排序 memset(sum, 0, sizeof sum); //初始化为0 for(int i = 1; i < cnt; i++) { ans[i] = tp[i].right; sum[cnt - i] = sum[cnt - i + 1] + tp[cnt - i].cnt; } int q; cin>>q; long long out = 0; for(int i = 1; i <= q; i++) { cin>>s; int pos = lower_bound(ans + 1, ans + cnt, s) - ans; //二分查找结果 out = (out + 1ll * i * sum[pos] % mod) % mod; } cout<<out<<endl; } return 0;}
0 0
- ZOJ 3940 Modulo Query(优先队列)
- ZOJ 3940Modulo Query
- Zoj 3940 Modulo Query
- zoj 1097 优先队列
- zoj 2724 优先队列
- ZOJ-2339 哈夫曼树 优先队列
- ZOJ 3953 贪心+优先队列
- zoj 3230Solving the Problems//优先队列
- ZOJ 3652 Maze 优先队列 模拟
- ZOJ 1649 - Rescue BFS/优先队列
- ZOJ 3230 Solving the Problems(优先队列)
- zoj 2724 Windows Message Queue 优先队列
- ZOJ 2724--Problem Set(优先队列)
- ZOJ 2526(最短路+优先队列)
- zoj 3103 Cliff Climbing 优先队列+BFS
- zoj 3230 Solving the Problems (优先队列)
- ZOJ 3888 Twelves Monkeys (预处理+优先队列)
- ZOJ 3888 Twelves Monkeys (优先队列+预处理)
- IOS 手势学习网址
- Quartz2d水印图片做法
- 一键把.app 输出为 .ipa
- UVa 725 Division
- 创建Linux内核函数的Man手册
- ZOJ 3940 Modulo Query(优先队列)
- 手势的使用方法
- 美团Android DEX自动拆包及动态加载简介
- C++以任意一个字符为分隔符,读取一行内容,显示到控制台
- Java编程入门:前言
- ListView封装实现下拉刷新和上拉加载
- BMP图片格式详细解析--以256色为例还原256色BMP图像数据
- Android gradle proguard 代码混淆详解
- linux上NFS客户端登陆错误