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. android - TextView单行显示...或者文字左右滚动(走马灯效果)

    条件 TextView单行显示,文字左右滚动(走马灯效果)实现条件: 实现单行设置固定宽度或者设置权重都行 代码 TextView滚动必须写下面几个属性 android:singleLine=&quo ...

  2. Android 之文件夹排序

    按文件名排序 /** * 按文件名排序 * @param filePath */ public static ArrayList<String> orderByName(String fi ...

  3. HttpClient 报错 Invalid cookie header, Invalid 'expires' attribute: Thu, 01 Jan 1970 00:00:00 GMT

    今天在给我姐夫写一个 QQ 自动加好友的程序,但是在 HttpClient 登陆 QQ 的时候报了一个错: -- ::] - Invalid cookie header: Jan :: GMT -- ...

  4. 【Oracle教程资源大合集】Oracle数据库免费学习资源汇总

    Oracle的产品非常丰富,各类学习资源也五花八门,本文将介绍Oracle官方的免费教程与风哥整理的Oracle视频教程: 1.Oracle帮助中心 Oracle帮助中心也称为Oracle文档中心,这 ...

  5. oracle相关函数

    (大写的PS:oracle存储过程测试进不去解决方案:重新编译:) TRUNC(sysdate, 'd') + 1   ////表示今天所在周的周一的年月日,如今天是2016.04.21周四,则TRU ...

  6. androidkiller连接模拟器并修改源码调试

    首先需要连接模拟器,首先在模拟器的bin目录下运行命令:nox_adb.exe connect 127.0.0.1:62001(可以disconnect关闭): 之后在androidkiller的bi ...

  7. Webstorm 2017.3激活破解

    之前尝试过各种激活破解办法,不过随着版本的不断升级,激活信息都失效了(毕竟咱不是通过正常途径激活的),只能重新激活.而且难度越来越大,记得早先网上有人分享激活码,激活的server地址,破解程序等等, ...

  8. 关于Knowledge Transfer的一点想法

    维基百科中对于Knowledge Transfer(知识转移)的定义是: 知识转移是指分享或传播知识并为解决问题提供投入.在组织理论中,知识转移是将知识从组织的一个部分转移到另一个部分的实践问题. 与 ...

  9. marathon传参一

    今天试了下marathon传参,新建一个job,增加一个参数,然后用cmd方式,echo出来 定义的json: { "id": "test1", "l ...

  10. Python支付宝在线支付API

    一.蚂蚁金服开发平台申请测试账号 a. 登陆蚂蚁金服开放平台https://open.alipay.com/platform/manageHome.htm,在“开发中心”—“研发服务”下拉处选择沙箱作 ...