做法①:RMQ(预处理NLOGN+后续跳跃蜜汁复杂度)

满足题意的区间的条件转换:

1.长度为R-L+1则最大值也为R-L+1

2.区间内的数不重复

当RMQ(L,R)!=R-L+1时 因为已经保证了 i~r[i] 之间的数不重复 则RMQ(L,R)必定大于当前的R-L+1 所以我们需要至少跳到 i+RMQ(L,R)-1

#include<bits/stdc++.h>
using namespace std;
int a[], r[];
int where[];
int dp[][];
int n,ans;
void rmqinit() {
for (int i = ; i <= n; i++) {
dp[i][] = a[i];
}
for (int j = ; ( << j) <= n; j++) {
for (int i = ; i + ( << j) - <= n; i++) {
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
}
}
int rmq(int l, int r) {
int x = ;
while ( << (x + ) <= r - l + ) {
x++;
}
return max(dp[l][x], dp[r - ( << x) + ][x]);
}
int main() {
cin >> n;
r[n] = n;
for (int i = ; i <= n; i++) {
cin >> a[i];
}
rmqinit();
where[a[n]] = n;
for (int i = n - ; i >= ; i--) {
if (where[a[i]]) {
r[i] = min(r[i + ], where[a[i]] - );
} else {
r[i] = r[i + ];
}
where[a[i]] = i;
}
for(int i=;i<=n;i++)
{
int j=i;
while(j<=r[i])
{
if(rmq(i,j)==j-i+)
{
ans++;
j++;
}
else
{
j=i+rmq(i,j)-;
}
}
}
cout<<ans<<endl;
}

做法②:哈希(O(N))

给每个数一个哈希值 从左往右扫一次 从右往左扫一次 如果扫到1就停下检查答案直到数组末尾或碰到下一个1  注意单个的1每次只能算一次

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> p;
const int MAXN = ;
int n, ans, T;
ll num[MAXN];
p hsh[MAXN];//每个数的哈希值
p prehsh[MAXN];//数组前缀的哈希值
p sumhsh[MAXN];//1~X数的哈希值
p update(p x, p y) { //哈希异或计算
x.first ^= y.first;
x.second ^= y.second;
return x;
}
int getans(int x) {
ll maxn = ; //从第一个1到下一个1或末端所经过的所有数最大值
ll r = x; //现在遍历到哪个数
int now = ; //目前符合条件的答案
while (r < n && num[r + ] != ) { //如果还没有到头且下一个不是1
r++; //到达下一个
maxn = max(maxn, num[r]); //维护最大值
if (r - maxn >= ) {
p xx;
xx = update(prehsh[r], prehsh[r - maxn]);
if (xx == sumhsh[maxn]) {
now++; //如果最大值不超过遍历过的数的数量且子串的哈希值与sumhsh[maxn]对应则答案++
}
}
}
return now;
}
int main() {
ll x = ;
cin >> n;
for (int i = ; i <= n; i++) {
cin >> num[i];
x ^= num[i];
}
for (int i = ; i <= n; i++) { //分配1~n对应每个值的哈希值
hsh[i].first = x ^ rand();
hsh[i].second = x ^ rand();
sumhsh[i] = hsh[i];
if (i != ) {
sumhsh[i] = update(sumhsh[i], sumhsh[i - ]); //计算数字1~i的哈希前缀
}
}
for (T = ; T <= ; T++) {
for (int i = ; i <= n; i++) {
prehsh[i] = hsh[num[i]];
if (i != ) {
prehsh[i] = update(prehsh[i], prehsh[i - ]); //计算数组前i个数的哈希前缀
}
}
for (int i = ; i <= n; i++) {
if (num[i] == ) {
if (T == ) { //单个1只能从单个方向计算一次
ans++;
}
ans += getans(i);
}
}
reverse(num + , num + + n);
}
cout << ans << endl;
return ;
}

Codeforces 1175F The Number of Subpermutations的更多相关文章

  1. Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)

    Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...

  2. Codeforces 1175F The Number of Subpermutations (思维+rmq)

    题意: 求区间[l, r]是一个1~r-l+1的排列的区间个数 n<=3e5 思路: 如果[l,r]是一个排列,首先这里面的数应该各不相同,然后max(l,r)应该等于r-l+1,这就能唯一确定 ...

  3. Codeforces 55D Beautiful Number

    Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisibl ...

  4. Codeforces 40 E. Number Table

    题目链接:http://codeforces.com/problemset/problem/40/E 妙啊... 因为已经确定的格子数目严格小于了$max(n,m)$,所以至少有一行或者一列是空着的, ...

  5. Codeforces 124A - The number of positions

    题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't ...

  6. codeforces Soldier and Number Game(dp+素数筛选)

    D. Soldier and Number Game time limit per test3 seconds memory limit per test256 megabytes inputstan ...

  7. Codeforces 55D Beautiful Number (数位统计)

    把数位dp写成记忆化搜索的形式,方法很赞,代码量少了很多. 下面为转载内容:  a positive integer number is beautiful if and only if it is  ...

  8. Codeforces 980E The Number Games 贪心 倍增表

    原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...

  9. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

随机推荐

  1. Arduino基础入门篇-进入Arduino的世界

    写在前面,首先是发现有网友对Arduino做了介绍,而且介绍比较清晰到位,就引用过来了. 文章出处:https://blog.csdn.net/TonyIOT/article/details/8091 ...

  2. 【计算机】DMA原理1

    DMA原理:DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量中断负载.否则,CPU 需要从来源把 ...

  3. NDK学习笔记-gdb调试

    在做开发的时候,难免会crash,那么在这时候需要进行调试,在C/C++的代码调试中,gdb是很常用的gdb在这不做过多介绍,之前在C语言中已经做过总结,这里简要回顾一下 要使用gdb,在编译的时候需 ...

  4. du 和 df命令

    测试环境数据库收到磁盘报警时,需要清理部分磁盘空间 df -h 查看整个磁盘占有 找到对应目录 查看每个文件夹占有磁盘量: sudo du -h --max-depth=1 data/ --max-d ...

  5. DISCO Presents Discovery Channel Code Contest 2020 Qual Task E. Majority of Balls

    Not able to solve this problem during the contest (virtual participation). The first observation is ...

  6. Photon Server初识(四) --- 部署自己的服务Photon Server

    准备工作: 1.一台 window 虚拟机(本机是window也行) 2.下载SDK : https://www.photonengine.com/zh-CN/sdks#server 一:SDK介绍 ...

  7. android中sqlite数据库的基本使用和添加多张表

    看了很多关于android使用sqlite数据库的文章,很多都是介绍了数据库的建立和表的建立,而表通常都是只建立一张,而实际情况我们用到的表可能不止一张,那这种情况下我们又该怎么办呢,好了,下面我教大 ...

  8. Log4net采用外部配置文件和多记录器的方法

    1) 创建配置文件,可以放在任意位置,名字可以任意的xml文件 例如,文件名 Log.Config.xml,内容如下 <?xml version="1.0" encoding ...

  9. servlet报错“严重: Allocate exception for servlet 类名java.lang.ClassNotFoundException: 路径. 类名”可能原因

    1.WEB-INF下web.xml中<servlet-class>路径错误,正确路径为 <servlet-class>包名.类名</servlet-class> 2 ...

  10. X509证书在window server 2003/IIS 6环境部署

    利用makecert.exe工具生成的X509证书在winform程序中运行正常,但是给部署在IIS中的应用程序用却获取不到证书信息,返回为空.原因是,iis没有权限读取位于证书存储区的X509证书, ...