Yura and Developers

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

  

Input

  

Output

  

Sample Input

  4 3
  5 2 4 4

Sample Output

  2

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

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9 + ; int n, k;
s64 val[ONE];
int pre[ONE], suc[ONE];
s64 sum[ONE], sum_B[ONE];
s64 Ans; vector <int> A[ONE], B[ONE]; int get()
{
int res;char c;
while( (c=getchar())< || c> );
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res;
} void Deal_first()
{
int stk[ONE], top = ;
for(int i = ; i <= n; i++)
{
while(top && val[i] > val[stk[top]])
suc[stk[top--]] = i - ;
pre[i] = stk[top] + ;
stk[++top] = i;
}
while(top) suc[stk[top--]] = n; for(int i = ; i <= n; i++)
sum[i] = (sum[i - ] + val[i]) % k;
for(int i = n; i >= ; i--)
sum_B[i] = (sum_B[i + ] + val[i]) % k; for(int i = ; i <= n; i++)
{
A[sum[i]].push_back(i);
B[sum_B[i]].push_back(i);
}
} int Get(int l, int r)
{
int res = sum[r] - sum[l - ];
if(res < ) res += k;
return res;
}
int Find(int R, int val)
{
if(A[val].size() == ) return ;
int l = , r = A[val].size() - ;
while(l < r - )
{
int mid = l + r >> ;
if(A[val][mid] > R) r = mid;
else l = mid;
}
if(A[val][l] > R) return l;
if(A[val][r] > R) return r;
return A[val].size();
}
int Query_left(int L, int R, int val) //sum [L,L~R] num of val
{
if(L > R) return ;
int now = sum[L - ]; //[1, L - 1]
int need = (now + val) % k; //1 ~ R the num of presum = need
return Find(R, need) - Find(L - , need);
}
void Deal_left(int l, int mid, int r)
{
int T = val[mid] % k;
for(int i = l; i <= mid - ; i++)
{
int now = Get(i, mid - );
int need = (T - now + k) % k;
Ans += Query_left(mid, r, need);
} Ans += Query_left(mid, r, T) - ;
} int Get_B(int l, int r)
{
int res = sum_B[l] - sum_B[r + ];
if(res < ) res += k;
return res;
}
int Find_B(int R, int val)
{
if(B[val].size() == ) return ;
int l = , r = B[val].size() - ;
while(l < r - )
{
int mid = l + r >> ;
if(B[val][mid] > R) r = mid;
else l = mid;
}
if(B[val][l] > R) return l;
if(B[val][r] > R) return r;
return B[val].size();
}
int Query_right(int L, int R, int val)
{
if(L > R) return ;
int now = sum_B[R + ];
int need = (now + val) % k;
return Find_B(R, need) - Find_B(L - , need);
}
void Deal_right(int l, int mid, int r)
{
int T = val[mid] % k;
for(int i = mid + ; i <= r; i++)
{
int now = Get_B(mid + , i);
int need = (T - now + k) % k;
Ans += Query_right(l, mid, need);
}
Ans += Query_right(l, mid, T) - ;
} int main()
{
n = get(); k = get();
for(int i = ; i <= n; i++)
val[i] = get(); Deal_first(); for(int i = ; i <= n; i++)
{
if(i - pre[i] + <= suc[i] - i + )
Deal_left(pre[i], i, suc[i]);
else
Deal_right(pre[i], i, suc[i]);
} printf("%lld", Ans);
}

【Codeforces549F】Yura and Developers [单调栈][二分]的更多相关文章

  1. Looksery Cup 2015 F - Yura and Developers 单调栈+启发式合并

    F - Yura and Developers 第一次知道单调栈搞出来的区间也能启发式合并... 你把它想想成一个树的形式, 可以发现确实可以启发式合并. #include<bits/stdc+ ...

  2. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  3. bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...

  4. BZOJ1012最大数 [JSOI2008] 单调栈+二分

    正解:单调栈+二分查找(or,线段树? 解题报告: 拿的洛谷的链接quq 今天尝试学习了下单调栈,然后就看到有个博客安利了这个经典例题?于是就去做了,感觉还是帮助了理解趴quqqqqq 这题,首先,一 ...

  5. 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线

     区间计数   基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80   两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{ ...

  6. 【bzoj4237】稻草人 分治+单调栈+二分

    题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: ...

  7. 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1333275 这个题不是很 ...

  8. 【洛谷P1823】音乐会的等待 单调栈+二分

    题目大意:给定一个长度为 N 的序列,定义两个数 \(a[i],a[j]\) 相互看得见,意味着 \(\forall k\in [i+1,j-1],a[k]\le a[i],a[k]\le a[j]\ ...

  9. spoj MINSUB 单调栈+二分

    题目链接:点击传送 MINSUB - Largest Submatrix no tags  You are given an matrix M (consisting of nonnegative i ...

随机推荐

  1. ChromeSwitchySharp代理设置步骤

    步骤: 1.新增情景模式配置如下:   2.设置切换规则   3.先“直接连接”进行登录:然后切换到“自动切换模式”访问对应url

  2. python正则表达式函数match()和search()的区别详解

    match()和search()都是python中的正则匹配函数,那这两个函数有何区别呢? match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找 ...

  3. 项目UML设计--日不落战队

    [团队信息] 团队项目: 小葵日记--主打记录与分享模式的日记app 队名:日不落战队 队员信息及贡献分比例: 短学号 名 本次作业博客链接 此次作业任务 贡献分配 备注 501 安琪 http:// ...

  4. iOS开发应用程序生命周期

    各个程序运行状态时代理的回调: - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSD ...

  5. 软工网络15个人作业4-alpha阶段个人总结(201521123059 叶文柠)

    一.个人总结 (1) 类别 具体技能和面试问题 现在回答 毕业找工作时 语言 最拿手的计算机语言之一,代码量多少? 感觉自己没有最拿手的语言,而且拿手的在计算机网络这方面的,所以在软件变成这方面的代码 ...

  6. 阻塞 , 非阻塞 , 同步 ,异步 , I/O模型

    •阻塞,非阻塞:进程/线程要访问的数据是否就绪,进程/线程是否需要等待: •同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞:异步只需要I/O操作完成的通知,并不主动读写 ...

  7. RPC-原理及RPC实例分析

    还有就是:RPC支持的BIO,NIO的理解 (1)BIO: Blocking IO;同步阻塞: (2)NIO:Non-Blocking IO, 同步非阻塞; 参考:IO多路复用,同步,异步,阻塞和非阻 ...

  8. [剑指Offer] 45.扑克牌顺子

    题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决 ...

  9. 最新发现:Object.defineProperty()让数组的length属性变成只读

    将属性添加到对象, 或修改现有属性的特性---MSDN的解释. 语法 object.defineProperty(object, propertyname, descriptor) object: 必 ...

  10. 【以前的空间】vijos 1720 阿狸的打字机

    https://www.vijos.org/p/1720 作为一个一个蒟蒻,跪了三个星期,终于在蔡大神的帮助下a了.这题网上的题解很多,不过大都把题解写的太简单了(对因为大神的题解只有三个字:傻叉题) ...