codeforces-1142 (div1)
div1真难,现在就是后悔, 非常后悔
A.显然如果我们知道起点和终点是哪两个点,我们可以算出距离通过b / gcd(a,b)的方式求出需要走几步的。
并且数据范围似乎也允许我们这么做,所以直接枚举取最大小值就可以了
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
LL N,K,s,t;
LL gcd(LL a,LL b){
return b == ?a:gcd(b,a % b);
}
LL lcm(LL a,LL b){
return b / gcd(a,b);
}
LL check(LL s,LL t){
if(t < || t > N * K) return -;
if(s < || s > N * K) return -;
LL d = t - s;
while(d <= ) d += N * K;
while(d > N * K) d -= N * K;
return lcm(d,N * K);
}
LL solve(LL S){
if(S > N * K || S < ) return 1e18;
LL ans = 1e18;
for(int i = ; i < N ; i ++){
LL x = check(S,i * K + + t);
if(~x) ans = min(ans,x);
x = check(S,(i + ) * K + - t);
if(~x) ans = min(ans,x);
}
return ans;
}
LL solve2(LL S){
if(S > N * K || S < ) return ;
LL ans = ;
for(int i = ; i < N ; i ++){
LL x = check(S,i * K + + t);
if(~x) ans = max(ans,x);
x = check(S,(i + ) * K + - t);
if(~x) ans = max(ans,x);
}
return ans;
}
int main(){
scanf("%lld%lld%lld%lld",&N,&K,&s,&t);
LL ans = solve(s + );
ans = min(ans,solve(K + - s));
printf("%lld ",ans);
ans = solve2(s + );
ans = max(solve2(K + - s),ans);
printf("%lld",ans);
return ;
}
A
B.显然第一个全排列类似于题目重定义了一个全排列的顺序,那我们依照这个像字典序一样的东西,把需要查询的排列换回正常的序列。
题目就变成了区间查询一个序列内是否存在1 - N的全排列的环的问题。
事实上不难发现,每一个点如果要跳的话贪心的跳最近的下一个点是最好的,跳完整个全排列就是跳N - 1步的路程。
对于查询的预处理,想到的是预处理出一个数字r[i]表示i这个点为起点最近的终点使得之间包含一个全排列环
那么首先可以想到i点跳N - 1步的位置就是r[i],对于每个点,倍增一下就可以了,时间复杂度O(nlogn)
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,Q;
int Hash[maxn];
int b[maxn],near[maxn];
int fa[maxn],dp[maxn];
int nxt[maxn];
vector<int>Stack[maxn];
int find(int t){
if(t == fa[t]) return t;
return fa[t] = find(fa[t]);
}
const int SP = ;
int pa[maxn][SP];
int r[maxn];
int main(){
Sca3(N,M,Q);
for(int i = ; i <= N; i ++) Hash[read()] = i;
for(int i = ; i <= M; i ++) b[i] = Hash[read()];
for(int i = M; i >= ; i --){
int la = b[i] + ;
if(la == N + ) la = ;
if(!near[la]) nxt[i] = M + ;
else nxt[i] = near[la];
near[b[i]] = i;
}
for(int i = ; i <= M ; i ++) pa[i][] = nxt[i];
pa[M + ][] = M + ;
for(int i = ; i < SP; i ++){
for(int j = ; j <= M + ; j ++){
pa[j][i] = pa[pa[j][i - ]][i - ];
}
}
//cout << pa[1][0] << endl;
N--;
for(int i = ; i <= M ; i ++){
r[i] = i;
for(int j = SP - ; j >= ; j --){
if(N & ( << j)) r[i] = pa[r[i]][j];
}
}
for(int i = M - ; i >= ; i --) r[i] = min(r[i],r[i + ]);
while(Q--){
int L,R; Sca2(L,R);
if(R < r[L]) printf("");
else printf("");
}
return ;
}
B 倍增
事实上还是有O(n)的做法的,如果将每一个点往他的前驱连边,就会发现形成一颗树,节点t的答案就是往上数N个祖先。
这就可以线性做出来了。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,Q;
int Hash[maxn];
int b[maxn],near[maxn];
int fa[maxn],dp[maxn];
int nxt[maxn];
vector<int>Stack[maxn];
int find(int t){
if(t == fa[t]) return t;
return fa[t] = find(fa[t]);
}
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],tot;
void init(){
for(int i = ; i <= M + ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v){
// cout << u << ' ' << v << endl;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int r[maxn];
int pos[maxn],dep[maxn];
void dfs(int t){
pos[dep[t]] = t;
if(dep[t] >= N) r[t] = pos[dep[t] - N + ];
else r[t] = M + ;
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to; dep[v] = dep[t] + ;
dfs(v);
}
}
int main(){
Sca3(N,M,Q); init();
for(int i = ; i <= N; i ++) Hash[read()] = i;
for(int i = ; i <= M; i ++) b[i] = Hash[read()];
for(int i = M; i >= ; i --){
int la = b[i] + ;
if(la == N + ) la = ;
if(!near[la]) nxt[i] = M + ;
else nxt[i] = near[la];
near[b[i]] = i;
}
for(int i = ; i <= M ; i ++) add(nxt[i],i);
dep[M + ] = ;
dfs(M + );
for(int i = M - ; i >= ; i --) r[i] = min(r[i],r[i + ]);
while(Q--){
int L,R; Sca2(L,R);
if(R < r[L]) printf("");
else printf("");
}
return ;
}
B dfs
codeforces-1142 (div1)的更多相关文章
- codeforces 407 div1 B题(Weird journey)
codeforces 407 div1 B题(Weird journey) 传送门 题意: 给出一张图,n个点m条路径,一条好的路径定义为只有2条路径经过1次,m-2条路径经过2次,图中存在自环.问满 ...
- codeforces 407 div1 A题(Functions again)
codeforces 407 div1 A题(Functions again) Something happened in Uzhlyandia again... There are riots on ...
- codeforces #305 div1 done
总算搞定了这一场比赛的题目,感觉收获蛮大 其中A,B,C都能通过自己的思考解决掉 D题思路好神,E题仔细想想也能想出来 以后坚持每两天或者一天做一场CF的div1的全套题目 除非有实在无法做出来的题目 ...
- Codeforces #254 div1 B. DZY Loves FFT 暴力乱搞
B. DZY Loves FFT 题目连接: http://codeforces.com/contest/444/problem/B Description DZY loves Fast Fourie ...
- codeforces #313 div1 E
首先我们要注意到一个事情 如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖 对于当前灯塔向右覆盖也是同理 那么我们只需要记录当前覆盖到的端点就可以完 ...
- codeforces #313 div1 D
好神的题目! 首先我们运用pick定理A=S-B/2+1将要求的东西转化掉 之后分离变量,我们变成了求选取凸包面积的期望和求选取凸包在边界上的点的期望 我们先考虑求选取凸包面积的期望 如何计算凸多边形 ...
- codeforces #313 div1 C
同BZOJ 3782 上学路线 QAQ 还比那个简单一点 把坐标(1,1)-(n,m)平移成(0,0)-(n-1,m-1) 设dp[i]表示从(1,1)出发第一次经过障碍且到达第i个障碍的方案数 首先 ...
- codeforces #313 div1 B
模拟判定就可以了 判定字符串是否相等用hash来判断 QAQ 值得一提的是一开始我交的时候T了 结果我将递归的顺序调整了一下就A了 (并不知道为什么 #include<cstdio> #i ...
- codeforces #313 div1 A
捕获一只野生大水题! 首先我们知道边长为L的正三角形含有边长为1的小正三角形为L^2个 那么我们可以通过在六边形的正上,左下,右下补充正三角形使得原图形变成正三角形 然后再将补充的减去即可 #incl ...
- codeforces #310 div1 E
算得上是比较水的E题了吧,自己想了想写了写居然1A了 对于这道题,我们很容易想到对于原图的一个边双,定向后任意两点间一定可达 那么我们可以求出原图的边双并将每个边双缩成一个点 那么原图就变成了无环的无 ...
随机推荐
- MIUI12系统怎么样开启Root超级权限的流程
MIUI12系统能有啥方法开启root超级权限?各位都清楚,Android机器有root超级权限,如果手机开启root相关权限,可以实现更好的功能,举例子,各位公司的营销部门,使用某些营销软件都需要在 ...
- Docker 创建 Bamboo6.7.1 以及与 Crowd3.3.2 实现 SSO 单点登录
目录 目录 1.介绍 1.1.什么是 Bamboo? 2.Bamboo 的官网在哪里? 3.如何下载安装? 4.对 Bamboo 进行配置 4.1.获取授权许可 4.2.一般配置 4.3.数据库配置 ...
- 『C编程』学习笔记(1)
size_t类型详解: #include <cstddef> #include <iostream> #include <array> int main() { s ...
- Django学习笔记(3)--模板
模板 在实际的页面大多是带样式的HTML代码,而模板是一种带有特殊语法的html文件,这个html文件可以被django编译,可以传递参数进去, 实现数据动态化.在编译完成后,生成一个普通的html文 ...
- 一起刷LeetCode
题目列表: 题目 解答 26. 删除排序数组中的重复项 https://www.cnblogs.com/powercai/p/10791735.html 25. k个一组翻转链表 https://ww ...
- Object 与 T的差别 导致swagger 的model 显示的数据为空
情景复现: 在整合swagger的时候,自己对原本定于的Object的data做了修改,把Object修改为了T,data的set方法的返回类型由于编译器没有报错,就没有去做修改, 这个时候就导致了, ...
- WMI Explorer操作 和 powershell命令
powershell查看wmi root 空间 PS C:\Users\yyy> Get-WmiObject -Class __namespace -Namespace root | selec ...
- 探索PowerShell 【十三】WMI对象
原文:探索PowerShell ][十三]WMI对象 我记得在xp时代,经常使用的工具有一个叫做WMI Administrative Tools,是微软官方提供的用来查看.编辑WMI对象的,只是现在好 ...
- sql是最成功的第四代语言
SQL发展的前世今生 很多年前,两名年轻的IBM研究员将一门关系型语言带到了数据库领域,旨在使用声明性的方式来操作数据.从Don Chamberlin和Ramond Boyce发表"SEQU ...
- Python3 视频教程,全网最全的视频教程,爬虫,从入门到实战
需要联系我:QQ:1844912514 最新Python基础班+就业班视频教程 链接: python分布式爬虫打造搜索引擎链接: https://pan.baidu.com/s/1N7HL7U0gQX ...