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. Mac电脑 怎么导出安卓手机的相册

    1.mac上下载一个HandShaker 2.把电脑和手机设置在同一个wifi下 3.安卓手机上下载一个HandShaker 参考:https://zhidao.baidu.com/question/ ...

  2. java的设计模式 - 外观模式(Facade)

    目的 看脸模式目的很简单,就是给用户留个好印象,不想让用户关注系统中的具体细节,关注系统的外表(暴露出来的接口)就好了.一些 GUI 的菜单也好,SDK 也好或多或少也会用到这种思想.这更多的是一种思 ...

  3. sql 上舍下舍運用

    [四舍五入取整截取] select round(54.56,0) [向下取整截取] SELECT FLOOR(54.56) [向上取整截取]  SELECT   CEILING(13.15) --MS ...

  4. Microsoft Deployment Toolkit build 8456

    MDT build 8456的重大变化摘要. 支持的配置更新 Windows ADK for Windows 10,版本1809 Windows 10,版本1809 Configuration Man ...

  5. mybatis常见错误

    1.传入单个参数为list时 List<Objects> query(@param("list") List<String> list) <selec ...

  6. HTML基础-------HTML标签(3)

    HTML标签(3) 表格 作用:制作一个表格 属性: 标签;table>tr>td(或者th) 语义; table:一个表格 tr:一行 td:一个单元格 th:单元格的表头 captio ...

  7. vue源码分析—Vue.js 源码构建

    Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下.(Rollup 中文网和英文网) 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.j ...

  8. CSAPP:第十章 系统级I/O

    CSAPP:第十章 系统级I/O 10.1 unix I/O10.2 文件10.3 读取文件元数据10.4 读取目录内容10.5 共享文件10.6 我们该使用哪些I/O函数? 10.1 unix I/ ...

  9. 华为笔记HOSTS,便于访问云端存储

    # Copyright (c) - Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windo ...

  10. EntityFramework Core指定更新导航属性了解一下?

    前言 本文来自和何镇汐大哥的探讨,很多时候我习惯于和别人交流过后会思考一些问题,无论是天马行空还是浅薄的想法都会记录下来,或许看到此博文的您能给我更多的思考,与人交流总能收获很多东西,出发点不一样则结 ...