做法①: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. 【转载】DOS系统的安装

    <电脑爱好者>报转载第一辑第一篇之DOS系统的安装 DOS系统的安装 一.DOS的历史 DOS是Diskette Operating System的缩写,意思是磁盘操作系统,主要有MS-D ...

  2. 洛谷 题解 P2802 【回家】

    思路:DFS+剪枝 本题可以用一个字符二维数组来存整个地图,然后在往四个方向进行搜索.注意:当走到家门前要先判断血量!(本人就被坑了) 代码: #include<bits/stdc++.h> ...

  3. js 中json遍历 添加 修改 类型转换

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. ESXi 虚拟机 提示 无法打开本地虚拟机的 xxx.vmx 的本地管道的 问题解决.

    1. 今天同事与我联系, 说一个虚拟机出现连不上, vcenter控制台关闭虚拟机之后 再次打开报错: 2. 自己最开始的解决方法 移除虚拟机, 进入服务器的datastore 重新注册, 结果发现问 ...

  5. Docker daemon.json 的配置项目合集

    这几天看了一点docker相关的东西, 在学习中: 看了下园友的blog 感觉很好 这里 学习一下. https://www.cnblogs.com/pzk7788/p/10180197.html 其 ...

  6. PL/SQL developer 11.0注册码

    PL/SQL developer 11.0注册码:product key:lhsw85g33x4p7leqk63hy8q28ffxzzvbxlserial No:193085password:xs37 ...

  7. Python+request超时和重试

    Python+request超时和重试 一.什么是超时? 1.连接超时 连接超时指的是没连接上,超过指定的时间内都没有连接上,这就是连接超时.(连接时间就是httpclient发送请求的地方开始到连接 ...

  8. 第7章:LeetCode--算法:递归问题

    70. Climbing Stairs This problem is a Fibonacci problem.F(n)=F(n-1)+F(n-2);Solving this problem by r ...

  9. Ubuntu系统降内核

    本人安装的Ubuntu16.04.6系统原生内核为4.15.0,但安装的应用仅支持4.8.0以下内核,因此需要降内核.PS:降内核有风险,操作前请慎重 1.查看可用的内核 输入命令查看已经可用的内核 ...

  10. print() 默认是打印完字符串会自动添加一个换行符

    可以使用end="  " 参数告诉 print() 用空格代替换行 for i in range(1,10): ... print(i,end=' ') ... 1 2 3 4 5 ...