【Codeforces549F】Yura and Developers [单调栈][二分]
Yura and Developers
Time Limit: 20 Sec Memory Limit: 512 MB
Description
Input
Output
Sample Input
5 2 4 4
Sample Output
HINT
Solution
首先,我们先用单调栈求出以点 i 作为最大值的区间 [pre_i, suc_i]。然后显然就是 求 [pre_i, suc_i] 内有几个区间的和与val[i] %k同余。
我们记区间为 [L, mid, R](i 为mid,pre_i 为 L,suc_i 为R),显然我们可以枚举长度小的半个区间。这时效率是O(nlogn)的。
那么只要能求出另外一半的贡献即可,假定我们枚举 [L, mid - 1] 的一个 点begin。那么 [begin, mid - 1] 的和是固定的,我们又知道总和应该为多少(%k同余)。所以我们就可以知道剩下需要提供多少值。 问题就转化为了求:[mid, mid ~ R] 中有几个以 mid 为左端点,mid~R为右端点的区间 的和 %k余 一个定值。
我们考虑这个东西怎么求,显然可以将问题转化为查前缀和形式:
我们已知 [1, mid - 1] 的和%k的值,又由于[mid, mid~R] 要提供一个定值的贡献,所以可以算出 [1, mid~R] 要余多少。
那么我们就可以通过查前缀和解决这个子问题,现在的问题又转化为了 如何查询一个区间 [L, R] 内某一定值数的个数:
显然我们可以 把位置加入在一个以值为下标的vector中,在这个vector中,二分查询位置<=R的个数即可,减去 <=(L - 1) 的即可。
这样我们就解决了假定[L, mid - 1]固定的一部分,假定[mid + 1, R]固定同理。
我们就解决了这道题啦!QWQ
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<vector> 9 using namespace std; 10 typedef long long s64; 11 12 const int ONE = 1000005; 13 const int MOD = 1e9 + 7; 14 15 int n, k; 16 s64 val[ONE]; 17 int pre[ONE], suc[ONE]; 18 s64 sum[ONE], sum_B[ONE]; 19 s64 Ans; 20 21 vector <int> A[ONE], B[ONE]; 22 23 int get() 24 { 25 int res;char c; 26 while( (c=getchar())<48 || c>57 ); 27 res=c-48; 28 while( (c=getchar())>=48 && c<=57 ) 29 res=res*10+c-48; 30 return res; 31 } 32 33 void Deal_first() 34 { 35 int stk[ONE], top = 0; 36 for(int i = 1; i <= n; i++) 37 { 38 while(top && val[i] > val[stk[top]]) 39 suc[stk[top--]] = i - 1; 40 pre[i] = stk[top] + 1; 41 stk[++top] = i; 42 } 43 while(top) suc[stk[top--]] = n; 44 45 for(int i = 1; i <= n; i++) 46 sum[i] = (sum[i - 1] + val[i]) % k; 47 for(int i = n; i >= 1; i--) 48 sum_B[i] = (sum_B[i + 1] + val[i]) % k; 49 50 for(int i = 1; i <= n; i++) 51 { 52 A[sum[i]].push_back(i); 53 B[sum_B[i]].push_back(i); 54 } 55 } 56 57 int Get(int l, int r) 58 { 59 int res = sum[r] - sum[l - 1]; 60 if(res < 0) res += k; 61 return res; 62 } 63 int Find(int R, int val) 64 { 65 if(A[val].size() == 0) return 0; 66 int l = 0, r = A[val].size() - 1; 67 while(l < r - 1) 68 { 69 int mid = l + r >> 1; 70 if(A[val][mid] > R) r = mid; 71 else l = mid; 72 } 73 if(A[val][l] > R) return l; 74 if(A[val][r] > R) return r; 75 return A[val].size(); 76 } 77 int Query_left(int L, int R, int val) //sum [L,L~R] num of val 78 { 79 if(L > R) return 0; 80 int now = sum[L - 1]; //[1, L - 1] 81 int need = (now + val) % k; //1 ~ R the num of presum = need 82 return Find(R, need) - Find(L - 1, need); 83 } 84 void Deal_left(int l, int mid, int r) 85 { 86 int T = val[mid] % k; 87 for(int i = l; i <= mid - 1; i++) 88 { 89 int now = Get(i, mid - 1); 90 int need = (T - now + k) % k; 91 Ans += Query_left(mid, r, need); 92 } 93 94 Ans += Query_left(mid, r, T) - 1; 95 } 96 97 98 int Get_B(int l, int r) 99 { 100 int res = sum_B[l] - sum_B[r + 1]; 101 if(res < 0) res += k; 102 return res; 103 } 104 int Find_B(int R, int val) 105 { 106 if(B[val].size() == 0) return 0; 107 int l = 0, r = B[val].size() - 1; 108 while(l < r - 1) 109 { 110 int mid = l + r >> 1; 111 if(B[val][mid] > R) r = mid; 112 else l = mid; 113 } 114 if(B[val][l] > R) return l; 115 if(B[val][r] > R) return r; 116 return B[val].size(); 117 } 118 int Query_right(int L, int R, int val) 119 { 120 if(L > R) return 0; 121 int now = sum_B[R + 1]; 122 int need = (now + val) % k; 123 return Find_B(R, need) - Find_B(L - 1, need); 124 } 125 void Deal_right(int l, int mid, int r) 126 { 127 int T = val[mid] % k; 128 for(int i = mid + 1; i <= r; i++) 129 { 130 int now = Get_B(mid + 1, i); 131 int need = (T - now + k) % k; 132 Ans += Query_right(l, mid, need); 133 } 134 Ans += Query_right(l, mid, T) - 1; 135 } 136 137 int main() 138 { 139 n = get(); k = get(); 140 for(int i = 1; i <= n; i++) 141 val[i] = get(); 142 143 Deal_first(); 144 145 for(int i = 1; i <= n; i++) 146 { 147 if(i - pre[i] + 1 <= suc[i] - i + 1) 148 Deal_left(pre[i], i, suc[i]); 149 else 150 Deal_right(pre[i], i, suc[i]); 151 } 152 153 printf("%lld", Ans); 154 }
View Code
转载于:https://www.cnblogs.com/BearChild/p/7687652.html
【Codeforces549F】Yura and Developers [单调栈][二分]相关推荐
- 【Codeforces 549F】Yura and Developers | 单调栈、启发式合并、二分
题目链接:https://codeforces.com/problemset/problem/549/F 题目大意: 给定一个序列和一个mod值,定义[l,r]合法当l到r的所有元素和减去其中的最大值 ...
- Looksery Cup 2015 F - Yura and Developers 单调栈+启发式合并
F - Yura and Developers 第一次知道单调栈搞出来的区间也能启发式合并... 你把它想想成一个树的形式, 可以发现确实可以启发式合并. #include<bits/stdc+ ...
- Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】
正题 题目链接:https://loj.ac/problem/2880 题目大意 给出平面上的nnn个点,然后求有多少个矩形满足 左下角和右上角各有一个点 矩形之间没有其他点 1≤n≤2×105,1≤ ...
- bzoj 4237: 稻草人(CDQ分治+单调栈+二分)
4237: 稻草人 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1352 Solved: 594 [Submit][Status][Discus ...
- BZOJ 2388--旅行规划(分块单调栈二分)
2388: 旅行规划 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 405 Solved: 118 [Submit][Status][Discus ...
- 单调栈 or 线段树扫描线 ---- E. Delete a Segment [单调栈+二分] [扫描线处理空白位置的技巧乘2]
题目链接 题目大意: 给出nnn个线段代表集合,现在问若可以将其中任意一个线段删除,则能够形成最多多少个独立的集合(取并集后) 解题思路1: 首先我们先对线段按照起点排序 那么我们枚举删除的线段iii ...
- Looksery Cup 2015 F. Yura and Developers(单调栈+二分+分治)(难*)
题目链接 题意:给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 思路:日后补. #include<bits/stdc++.h> using namespace std; t ...
- BZOJ1767/Gym207383I CEOI2009 Harbingers 斜率优化、可持久化单调栈、二分
传送门--BZOJCH 传送门--VJ 注:本题在BZOJ上是权限题,在Gym里面也不能直接看,所以只能在VJ上交了-- 不难考虑到这是一个\(dp\). 设\(dep_x\)表示\(x\)在树上的带 ...
- 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]
题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...
最新文章
- windows下如何正确使用Jconsole远程连接linux主机上的JVM
- 管道过滤器模式(Pipe and Filter)与组合模式(修改)
- Django2.2-LookupError No installed app with label admin
- 今天项目中遇到的一个问题:判断新闻Id是否存在
- 无法加载安装程序库 wbemupgd.dll
- 周思进:产品和服务在“骂”与“被骂”中不断打磨
- TypeScript+vue使用与迁移经验总结
- mysql5.7循环,python3.4用循环往mysql5.7中写数据并输出的实现方法
- 修改Tomcat欢迎界面为自己项目界面
- 分页加载PullToRefreshLayout+PullableListView
- 专利号校验码php,电子专利证书的三种下载操作方法
- 2019-CS224n-Assignment2
- 视频时代的下一幕 ABC Inspire:读懂视频
- 【圆梦名企第三季】4月12日软件业“人才留湘 引才入湘”专项行动
- 自动化测试到底该怎么学?
- 超级好用的视频转换器Cisdem Video Converter for Mac
- 云服务器怎么安装虚拟显卡,云服务器怎么弄图形界面
- 计算机开关电源的发展,开关电源发展史及发展趋势剖析
- 一个月过软考|软件设计师中级考试经验分享
- spring boot 一个极简单的 demo 示例