题链:

http://codeforces.com/problemset/problem/549/F
题解:

分治,链表。
考虑对于一个区间[L,R],其最大值在p位置,
那么答案的贡献就可以分为3部分:
1.[L,p-1]中合法的区间
2.[p+1,R]中合法的区间
3.[L,R]中经过p的合法区间。
前两个因为是相同子问题,可以递归解决。
考虑如何求出3.的答案。
令S[i]表示$\sum_{k=1}^{i}A[i]$(即前缀和)
显然对于一组(l,r)表示的区间[l,r],
当且仅当满足L<=l<=p且p<r<=R(或L<=l<p且p<=r<=R),
并且 S[r]-S[l-1]-A[p]≡0 (mod K)时,才是合法区间。


但是如果直接递归实现,复杂度高达O(N^2)
所以预处理出每个元素在哪个包含它的最大区间里是最大值。
可以用单调栈O(N)维护出。
然后对于每个元素以及刚刚得出来的区间去计算贡献。
同时在计算贡献时,采用的方法是:
枚举一边的元素,然后用形如Query(ql,qr,qv)的方式去询问另一边S[*]==qv的个数
至于枚举哪一边,就是哪边短就枚举哪一边,这样可以保证询问次数为nlogn次的。
然后考虑如何询问。
如果采用主席树,则需要把复杂度再乘上一个log的询问代价,总的复杂度为O(N logN logN)
或者把询问离线成差分形式,插入链表,最后扫描链表O(N logN)得出答案(链表元素有N logN个),总的复杂度为O(N logN)
比如说对于询问Query(l,r,v)拆成两个(v,sign)的形式,我们在链表l-1中加入(v,-1),在链表r中加入(v,1)
最后从i=0到N扫描一遍,首先cnt[S[i]]++,(cnt[x]表示前缀i中x这个值出现了多少次)
然后再扫描i的询问链表,把ans+=cnt[v]*sign即可。
最后的ans既是答案。

代码:

#include<bits/stdc++.h>
#define MAXN 300050
#define INF 0x3f3f3f3f
using namespace std;
int N,K,more;
int A[MAXN],S[MAXN],L[MAXN],R[MAXN];
struct LINK{int lnt;int nxt[MAXN*20],val[MAXN*20],sign[MAXN*20],head[MAXN];LINK(){lnt=2;}void Add(int u,int v,int s){if(u<0) return;val[lnt]=v; sign[lnt]=s; nxt[lnt]=head[u]; head[u]=lnt++;}void Query(int l,int r,int v){Add(l-1,v,-1); Add(r,v,1);}long long Getans(){long long ret=0;static int cnt[1000050];for(int i=0;i<=N;i++){cnt[S[i]]++;for(int j=head[i];j;j=nxt[j])ret+=sign[j]*cnt[val[j]];}return ret;}
}Q;
void prework(){static int stk[MAXN],top;A[0]=A[N+1]=INF;stk[top=1]=0;for(int i=1;i<=N;i++){while(A[stk[top]]<=A[i]) top--;L[i]=stk[top]+1; stk[++top]=i;}stk[top=1]=N+1;for(int i=N;i>=1;i--){while(A[stk[top]]<A[i]) top--;R[i]=stk[top]-1; stk[++top]=i;}for(int i=1;i<=N;i++)S[i]=(S[i-1]+A[i])%K;
}
void solve(){int al,ar,qv,ql,qr,sign;for(int i=1;i<=N;i++){if(L[i]==R[i]) continue;more++;if(i-L[i]+1<=R[i]-i+1) al=L[i]-1,ar=i-1,ql=i,qr=R[i],sign=1;else al=i,ar=R[i],ql=L[i]-1,qr=i-1,sign=-1;for(int j=al;j<=ar;j++){qv=(1ll*S[j]+sign*A[i]%K+K)%K;Q.Query(ql,qr,qv);}}
}
int main(){scanf("%d%d",&N,&K);for(int i=1;i<=N;i++) scanf("%d",&A[i]);prework();solve();long long ans=Q.Getans();printf("%lld\n",ans-more);return 0;
}

  

转载于:https://www.cnblogs.com/zj75211/p/8541888.html

●CodeForces 549F Yura and Developers相关推荐

  1. codeforces 549F Yura and Developers(分治、启发式合并)

    codeforces 549F Yura and Developers 题意 给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 题解 分治,对于一个区间,找出最大值之后,分成两个区间. ...

  2. Codeforces 549F Yura and Developers

    Description 有一个长度为n的数组a,现在要找一个长度至少为2的子段,求出这一子段的和,然后减去最大值,然后对k取余结果为0. 问这样的子段有多少个 题面 Solution 考虑分治,普遍的 ...

  3. [分治] 51Nod1472 Codeforces #549F. Yura and Developers

    分治学傻的我只会无脑分治-- 题意就是求满足 sum≡maxsum \equiv max 的区间.反正就是按套路搞. 注意计数的数组不能每次 clearclear ,要开时间戳. #include&l ...

  4. Codeforces - Yura and Developers

    题目链接:Codeforces - Yura and Developers 有一个显然的2个log做法. 分治最大值,然后枚举小区间启发式计算答案. 但是其实可以一个log,因为分治的时候,对于区间形 ...

  5. 【Codeforces549F】Yura and Developers [单调栈][二分]

    Yura and Developers Time Limit: 20 Sec  Memory Limit: 512 MB Description Input Output Sample Input 4 ...

  6. Yura and Developers

    Yura and Developers 题目大意 给出一个长度为n的区间,求其中有多少个区间,使得这个区间中所有元素的和减去这个区间中的最大值除以k的余数为0. 代码 #include<cstd ...

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

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

  8. 【Codeforces 549F】Yura and Developers | 单调栈、启发式合并、二分

    题目链接:https://codeforces.com/problemset/problem/549/F 题目大意: 给定一个序列和一个mod值,定义[l,r]合法当l到r的所有元素和减去其中的最大值 ...

  9. [CF549F/51nod1472]Yura and Developers

    题目大意 有一个长度为n的数组a,现在要找一个长度至少为2的子段,求出这一子段的和,然后减去最大值,然后对k取余结果为0. 问这样的子段有多少个. 数据范围 1 ≤ n ≤ 300 000, 1 ≤  ...

最新文章

  1. 20幅漫画告诉你未来世界是怎样的
  2. DSP学习初阶的一些笔记
  3. Applese 的QQ群
  4. 浅谈ios设计之使用表格UITableVIew设计通讯录的方法
  5. 集中式整合之编写springsecurity配置类
  6. mysql数据导出不完正_【MySQL】mysqldump 导出数据 常见问题
  7. case when then的用法
  8. C/C++ ultoa函数 - C语言零基础入门教程
  9. [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
  10. 计算机的数据库应用领域,【信息管理论文】信息管理中计算机数据库技术的应用(共4410字)...
  11. C语言求超级素数的个数,求一个输出a-b的超级素数程序(c)
  12. ios13.4.1续航怎么样?
  13. 任正非华为为什么暂不推出鸿蒙,任正非表示,华为的鸿蒙系统已经上网?惊喜吗...
  14. jenkins sonar配置
  15. Windows10 中在指定目录下启动Powershell
  16. boost库asio错误码
  17. 基于SpringBoot实现简易的单点登录系统(提供gitee源码)
  18. 数据导入与预处理-第8章-实战演练-数据分析师岗位分析
  19. 4 款超级好用的终端文件管理器,提高你的使用效率!
  20. 四种常用聚类及代码(三):birch(一种层次聚类)

热门文章

  1. 计算机考研英语大纲,考研计算机大纲
  2. arm芯片中的浮点运算(一)
  3. PageHelper 插件踩过的坑
  4. 如何掌握程序语言(转自王垠Blog)
  5. Unity用UnityWebRequest和 BestHttp的GET和POST表单提交,与php交互
  6. Ubuntu16.04+CUDA8.0+GTX960M安装
  7. 【FreeSwitch开发实践】外呼网关配置(拨打电话)
  8. 在广州找前端开发实习经验分享1
  9. 一个SAPer的网络日志-连载四-三不主义下的项目经理
  10. SpringBoot2.6.5+Swagger3配置