Codeforces 1175F The Number of Subpermutations
做法①: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的更多相关文章
- Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)
Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...
- Codeforces 1175F The Number of Subpermutations (思维+rmq)
题意: 求区间[l, r]是一个1~r-l+1的排列的区间个数 n<=3e5 思路: 如果[l,r]是一个排列,首先这里面的数应该各不相同,然后max(l,r)应该等于r-l+1,这就能唯一确定 ...
- Codeforces 55D Beautiful Number
Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisibl ...
- Codeforces 40 E. Number Table
题目链接:http://codeforces.com/problemset/problem/40/E 妙啊... 因为已经确定的格子数目严格小于了$max(n,m)$,所以至少有一行或者一列是空着的, ...
- Codeforces 124A - The number of positions
题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't ...
- codeforces Soldier and Number Game(dp+素数筛选)
D. Soldier and Number Game time limit per test3 seconds memory limit per test256 megabytes inputstan ...
- Codeforces 55D Beautiful Number (数位统计)
把数位dp写成记忆化搜索的形式,方法很赞,代码量少了很多. 下面为转载内容: a positive integer number is beautiful if and only if it is ...
- Codeforces 980E The Number Games 贪心 倍增表
原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...
- Codeforces 980E The Number Games - 贪心 - 树状数组
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...
随机推荐
- 使用canal通过mysql复制协议从binlog实现热数据nosql缓存(1)
binlog: mysql在运行过程中执行的DML(增删改)操作都会以二进制形式记录在binlog中 canal server: canal server作为从数据库(slave)向主数据库发送dum ...
- 【AMAD】django-compressor -- 将JS和CSS文件压缩为一个缓存文件
简介 个人评分 简介 django-compressor1的example: {% load compress %} {% compress css %} <link rel="sty ...
- OpenCV.问题&解决
ZC:PDF:D:\_eBook\OpenCV\学习OpenCV(中文版Linuxidc.com).pdf 1.函数cvCaptureFromAVI(...) & cvCreateFileCa ...
- 学习笔记:CentOS7学习之二十:shell脚本的基础
目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...
- poj1797(dijstra变形,求最小边的最大值)
题目链接:https://vjudge.net/problem/POJ-1797 题意:n个点,m条带权边,求点1到点n的所有路径中最小边的最大值. 思路: 和poj2253一样,只不过那题n< ...
- Dijstra_优先队列_前向星
Dijstra算法求最短路径 具体实现方式 设置源点,将源点从原集u{}中取出并放入新建集s{} 找出至源点最近的点q从原集取出放入新集s{} 由q点出发,更新所有由q点能到达的仍处于原集的点到源点的 ...
- 封装PHP增删改查方法
<?php class sqlModel{ public $db; public function __construct(){ try{ $dbms='mysql';//数据库类型 $dbNa ...
- 【死磕Java并发】—–深入分析ThreadLocal
ThreadLoacal是什么? ThreadLocal是啥?以前面试别人时就喜欢问这个,有些伙伴喜欢把它和线程同步机制混为一谈,事实上ThreadLocal与线程同步无关.ThreadLocal虽然 ...
- TCP协议探究(一):报文格式与连接建立终止
一 TCP:传输控制协议报文格式 1 TCP服务 提供面向连接.可靠的字节流服务 面向连接意味着两方通信,不支持多播和广播 可靠性的支持: 应用数据被分割成TCP认为最适合发送的数据块.由TCP传递给 ...
- C#通讯框架改写
现有项目是利用C#的socket与PLC进行实时通讯,PLC有两种通讯模式——常规采集&高频采集. 其中常规采集大概在10ms左右发送一次数据,高频采集大概在2ms左右发送一次数据. 现有代码 ...