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)的更多相关文章

  1. codeforces 407 div1 B题(Weird journey)

    codeforces 407 div1 B题(Weird journey) 传送门 题意: 给出一张图,n个点m条路径,一条好的路径定义为只有2条路径经过1次,m-2条路径经过2次,图中存在自环.问满 ...

  2. codeforces 407 div1 A题(Functions again)

    codeforces 407 div1 A题(Functions again) Something happened in Uzhlyandia again... There are riots on ...

  3. codeforces #305 div1 done

    总算搞定了这一场比赛的题目,感觉收获蛮大 其中A,B,C都能通过自己的思考解决掉 D题思路好神,E题仔细想想也能想出来 以后坚持每两天或者一天做一场CF的div1的全套题目 除非有实在无法做出来的题目 ...

  4. Codeforces #254 div1 B. DZY Loves FFT 暴力乱搞

    B. DZY Loves FFT 题目连接: http://codeforces.com/contest/444/problem/B Description DZY loves Fast Fourie ...

  5. codeforces #313 div1 E

    首先我们要注意到一个事情 如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖 对于当前灯塔向右覆盖也是同理 那么我们只需要记录当前覆盖到的端点就可以完 ...

  6. codeforces #313 div1 D

    好神的题目! 首先我们运用pick定理A=S-B/2+1将要求的东西转化掉 之后分离变量,我们变成了求选取凸包面积的期望和求选取凸包在边界上的点的期望 我们先考虑求选取凸包面积的期望 如何计算凸多边形 ...

  7. codeforces #313 div1 C

    同BZOJ 3782 上学路线 QAQ 还比那个简单一点 把坐标(1,1)-(n,m)平移成(0,0)-(n-1,m-1) 设dp[i]表示从(1,1)出发第一次经过障碍且到达第i个障碍的方案数 首先 ...

  8. codeforces #313 div1 B

    模拟判定就可以了 判定字符串是否相等用hash来判断 QAQ 值得一提的是一开始我交的时候T了 结果我将递归的顺序调整了一下就A了 (并不知道为什么 #include<cstdio> #i ...

  9. codeforces #313 div1 A

    捕获一只野生大水题! 首先我们知道边长为L的正三角形含有边长为1的小正三角形为L^2个 那么我们可以通过在六边形的正上,左下,右下补充正三角形使得原图形变成正三角形 然后再将补充的减去即可 #incl ...

  10. codeforces #310 div1 E

    算得上是比较水的E题了吧,自己想了想写了写居然1A了 对于这道题,我们很容易想到对于原图的一个边双,定向后任意两点间一定可达 那么我们可以求出原图的边双并将每个边双缩成一个点 那么原图就变成了无环的无 ...

随机推荐

  1. linux添加crontab定时任务

    1.crontab -e命令进入linux定时任务编辑界面,举个简单的例子,比如我要定时往txt文件写入 */ * * * * .txt */1就是每隔一分钟像文件写入,其他一些详细的操作大家可以去网 ...

  2. 无限极分类(adjacency list)的三种方式(迭代、递归、引用)

    一般的分类树状结构有两种方式: 一种是adjacency list,也就是是id,parent id这中形式. 另一种是nested set,即左右值的形式. 左右值形式查询起来比较高效,无需递归等, ...

  3. First Show

    随便写写,记录美好生活 博客的内容主要是关于java后台开发所涉及到技术栈的学习记录

  4. spring boot跨域问题

    跨域是指不同域名之间相互访问.跨域,指的是浏览器不能执行其他网站的脚本.它是浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制.也就是如果在A网站中,我们希望使用Ajax来获得B网站 ...

  5. CentOS 7 最小安装网络配置

    通常最小安装是没有自动启动网络连接的,可以通过ifconfig或ip addr查看网络信息 (类似windows里的ipconfig),然而最小安装是没有ifconfig命令的, 这里我们使用ip a ...

  6. ajax实现用户登陆,退出,java做后端

    最近http老师布置了个任务,用cookie完成登陆,退出.Http老师讲的是node.js写后端,由于自己还是擅长java些,还是用Java做了. 以前跟着教程写过一个网站,当初是用jsp+serv ...

  7. 不停服务,动态加载properties资源文件

    系统运行过程中,我们用注解@Value("${****}")可以获取资源文件中的内 容,获取的内容会被存储在spring缓存中,因此如果我们修改了资源文件,要 想读取到修改后的内容 ...

  8. C++一些基本数据结构:字面常量、符号常量、枚举常量

    常量:C++包括两种常量,字面常量和符号常量. 字面常量:指的是直接输入到程序中的值 比如:in myAge=26: myAge是一个int类型变量,而26是一个字面常量. 符号常量:指的是用名称表示 ...

  9. react dnd demo2

    import React, { Component } from 'react'; import './App.css'; import Card from './Card'; import HTML ...

  10. 014_zk路径过滤分析

    一.线上zk访问延迟特别高需要统计一段时间内的zk写入路径top10,实现如下: #!/usr/bin/env python # -*- coding:utf-8 -*- import re,trac ...