【UER #1】[UOJ#12]猜数 [UOJ#13]跳蚤OS [UOJ#14]DZY Loves Graph

[UOJ#12]【UER #1】猜数

试题描述

这一天,小Y、小D、小C正在愉快地玩耍。

小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 n。

小D是个机灵鬼,很快从小Y嘴里套出了 n的值。然后在脑内把 n写成了 a×b的形式。其中 a,b 都是正整数。

小C是个八卦狂,他发现小D从小Y那里获知了神奇的东西,于是死缠烂打追问小D。最后小D说道:“我可以告诉你正整数 g和 l的值,我保证 ab=gl=n且 a,b都是 g 的倍数。但是 a,b 我可不能告诉你。”

这可急坏了小C。他决定退而求其次,找出 a+b 的最小值和最大值。请你帮帮他吧!

输入

第一行一个正整数 T,表示有 T组询问。

接下来 T行每行两个正整数 g,l 表示一组询问。

输出

对于每个询问输出一行两个正整数,分别表示 a+b的最小值与最大值。保证问题有解。

C/C++ 输入输出 long long 时请用 %lld。C++ 可以直接使用 cin/cout 输入输出。

输入示例1

1
1 4

输出示例1

4 5

输入示例2

1
2 8

输出示例2

8 10

数据规模及约定

g, l ≤ 1018

题解

注意 n 是完全平方数。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;
#define LL long long

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
    if(Head == tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        tail = (Head = buffer) + l;
    }
    return *Head++;
}
LL read() {
    LL x = 0, f = 1; char c = Getchar();
    while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
    while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
    return x * f;
}

#define maxn 70
LL prime[maxn];
int cnt, c[maxn];

int main() {
	int T = read();
	while(T--) {
		LL g = read(), l = read() / g;

		printf("%lld %lld\n", g * 2 * (LL)sqrt(l), g * (l + 1));
	}

	return 0;
}

[UOJ#13]【UER #1】跳蚤OS

试题描述

跳蚤OS 是跳蚤国自主研发的功能强大的操作系统。

跳蚤OS的文件系统与普通的文件系统类似,是个文件夹套文件夹的结构。文件系统根目录称为“/”。我们可以用文件路径来表明文件所在的位置,比如“/flea/uoj”表示根目录下的flea文件夹下的uoj文件。

跳蚤OS的文件系统中。快捷方式是一种特殊的文件夹,点开该快捷方式相当于打开该快捷方式指向的文件夹。

比如,如果有一个快捷方式 “/etc/abc”,该快捷方式指向 “/flea/def”这个文件夹,那么一旦访问“/etc/abc”就相当于访问“/flea/def”。

这一天,跳蚤国王正在使用跳蚤OS。初始时文件系统为空,只有根目录。他每次会进行如下操作:

  1. 首先,随便写出两个文件路径 s和 t。
  2. 接着,如果位置 t处不存在文件,则在该处创建一个空文件夹。
  3. 最后,跳蚤国王保证 s这个位置没有文件,于是在 s 处创建一个快捷方式指向 t 。如果 t 是个快捷方式,那么 s 将指向 t 所指向的文件夹。

上文所说的“创建”在父级目录不存在的时候要一并创建其父级目录。比如,假设文件系统里只有 “/v ” 这个文件夹,那么现在我创建 “/v/flea/king/qaq” 就会在文件系统中新增三个文件夹:“/v/flea”, “/v/flea/king”, “/v/flea/king/qaq”。

跳蚤国王进行了 n 次这样的操作后,开始不断问他的助手伏特:现在我如果在 p 这个路径处创建一个文件夹(如果已存在则不创建),那么这个文件夹的真实路径是什么?

于是伏特只好向你求助了,请你帮一帮他吧!请参照样例来更清晰地理解题意。

输入

第一行两个正整数n,m,表示跳蚤国王进行了n个操作,提了m个问题。

接下来n行每行两个用空格隔开的字符串s,t,表示跳蚤国王的一次操作。

接下来 m 行每行一个字符串 p 表示跳蚤国王的一个询问。

保证所有的 s,t,p 都是合法的文件路径。即,文件夹名一定是由小写英文字母组成的非空字符串,路径名一定形如“/xxx/xxx/xxx/.../xxx”这样子。保证当路径不为根目录“/”时,路径不以“/”结尾。

输出

对于跳蚤国王的每个询问输出真实路径。

输入示例1

6 5/root //duliu /picks/vfk /vfleaking/orz/orz/orz /duliu/otl /duliu/duliu/vfk/sb /vfleaking/vfk/sb/nothing/nothing/orz/orz/orz/orz/qaq/otl

输出示例1

/vfleaking/nothing/nothing/orz/picks/qaq/picks/duliu

输入示例2

2 3
/ba/la /
/w/o/w /w
/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la
/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba/la/ba
/w/o/w/o/w/o/w/o

输出示例2

/
/ba
/w/o

输入示例3

戳我下载

输出示例3

戳我下载

数据规模及约定

n ≤ 20000, m ≤ 10

题解

建立一棵 Trie 树,用类似AC自动机的思想,但是把 Fail 指针指向快捷方式所指的源文件。

注意这里的 Fail 指针仅在下一个字符为“/”生效,还有一些细节需要注意,这里不赘述了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;

int read() {
    int x = 0, f = 1; char c = getchar();
    while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
    return x * f;
}

#define maxn 500010
#define maxs 27
int n, q;
char S[maxn], A[maxn], B[maxn];

int ToT = 1, f[maxn], fa[maxn], ch[maxn][maxs], Q[maxn], hd, tl;
int idx(char t) { return t == ‘/‘ ? 26 : t - ‘a‘; }

int main() {
//	freopen("ex_os3.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	n = read(); q = read();
	for(int i = 1; i <= n; i++) {
		scanf("%s", S + 1); int len = strlen(S + 1);
		int u = 1;
		for(int j = 1; j <= len; j++) {
			int d = idx(S[j]);
			if(isalpha(S[j])) {
				if(!ch[u][d]) ch[u][d] = ++ToT, fa[ToT] = u;
				u = ch[u][d];
			}
			else {
				while(f[u]) u = f[u];
				if(!ch[u][d]) ch[u][d] = ++ToT, fa[ToT] = u;
				u = ch[u][d];
			}
		}
		while(f[u]) u = f[u];
		scanf("%s", S + 1); len = strlen(S + 1);
		int u2 = u; u = 1;
		for(int j = 1; j <= len; j++) {
			int d = idx(S[j]);
			if(isalpha(S[j])) {
				if(!ch[u][d]) ch[u][d] = ++ToT, fa[ToT] = u;
				u = ch[u][d];
			}
			else {
				while(f[u]) u = f[u];
				if(!ch[u][d]) ch[u][d] = ++ToT, fa[ToT] = u;
				u = ch[u][d];
			}
		}
		while(f[u]) u = f[u];
		if(len == 1) u = 1;
		f[u2] = u;
//		printf("%d %d\n", u2, u);
	}

	while(q--) {
		scanf("%s", S + 1); int len = strlen(S + 1);
		int u = 1, ca = 0, cb = 0; bool flag = 1;
		for(int i = 1; i <= len; i++) {
			int d = idx(S[i]);
			if(isalpha(S[i])) {
				if(!ch[u][d]) {
					flag = 0;
					for(; i <= len; i++) B[++cb] = S[i];
					break;
				}
				u = ch[u][d];
			}
			else {
				while(f[u]) u = f[u];
				if(!ch[u][d]) {
					for(; i <= len; i++) B[++cb] = S[i];
					break;
				}
				u = ch[u][d];
			}
		}
		if(flag) while(f[u]) u = f[u];
		while(fa[u]) {
			for(int i = 0; i < maxs; i++) if(ch[fa[u]][i] == u) {
				A[++ca] = i == 26 ? ‘/‘ : i + ‘a‘; break;
			}
			u = fa[u];
		}
//		printf("ans: ");
		for(int i = ca; i; i--) putchar(A[i]);
		for(int i = 1; i <= cb; i++) putchar(B[i]);
		if(ca + cb == 0) putchar(‘/‘);
		putchar(‘\n‘);
	}

	return 0;
}

[UOJ#14]【UER #1】DZY Loves Graph

试题描述

DZY开始有 n 个点,现在他对这 n 个点进行了 m 次操作,对于第 i 个操作(从 1 开始编号)有可能的三种情况:

  1. Add a b: 表示在 a 与 b 之间连了一条长度为 i 的边(注意,i 是操作编号)。保证 1≤a,b≤n。
  2. Delete k: 表示删除了当前图中边权最大的k条边。保证 k 一定不会比当前图中边的条数多。
  3. Return: 表示撤销第 i−1 次操作。保证第 1 次操作不是 Return 且第 i−1 次不是 Return 操作。

请你在每次操作后告诉DZY当前图的最小生成树边权和。如果最小生成树不存在则输出 0 。

输入

第一行两个正整数 n,m 。表示有 n 个点 m 个操作。 接下来 m 行每行描述一个操作。

输出

对于每一个操作输出一行一个整数表示当前最小生成树边权和。

输入示例1

2 2
Add 1 2
Return

输出示例1

1
0

输入示例2

5 10
Add 2 1
Add 3 2
Add 4 2
Add 5 2
Add 2 3
Return
Delete 1
Add 2 3
Add 5 2
Return

输出示例2

0
0
0
10
10
10
0
0
15
0

输入示例3

戳我下载

输出示例3

戳我下载

数据规模及约定

n≤3×105, m≤5×105

题解

仔细读题,发现可以做到每条边最多加进来一次,删除一次。(想一想,为什么)

有删除操作了,不能用路径压缩版并查集了,那么考虑用按秩合并的并查集做。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
    if(Head == tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        tail = (Head = buffer) + l;
    }
    return *Head++;
}
int read() {
    int x = 0, f = 1; char c = Getchar();
    while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
    while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
    return x * f;
}

#define maxn 300010
#define maxm 500010
#define LL long long
int n, m, cnt;
LL ans[maxm], sum[maxm];
bool yes[maxm];
struct Edge { int u, v; } es[maxm];
struct Que { int tp, a, b; } qs[maxm];

int pa[maxn], siz[maxn];
int findset(int x) { return x == pa[x] ? x : findset(pa[x]); }
void Union(int a, int b, int i) {
	a = findset(a); b = findset(b);
	es[++cnt] = (Edge){ a, b };
	sum[cnt] = sum[cnt-1]; yes[cnt] = yes[cnt-1];
	if(a == b) { ans[i] = ans[i-1]; return ; }
	if(siz[a] > siz[b]) swap(a, b);
	siz[b] += siz[a];
	pa[a] = b;
	sum[cnt] += (LL)i;
	yes[cnt] = (siz[b] == n);
	ans[i] = (siz[b] == n) ? sum[cnt] : 0;
	return ;
}
void Del(int x) {
	int a = es[x].u, b = es[x].v;
	if(a == b) return ;
	if(siz[a] > siz[b]) swap(a, b);
	siz[b] -= siz[a];
	pa[a] = a; pa[b] = b;
	return ;
}

int main() {
	n = read(); m = read();
	for(int i = 1; i <= m; i++) {
		char tc = Getchar();
		while(!isalpha(tc)) tc = Getchar();
		if(tc == ‘A‘) qs[i].tp = 1, qs[i].a = read(), qs[i].b = read();
		if(tc == ‘D‘) qs[i].tp = 2, qs[i].a = read(), qs[i].b = -1;
		if(tc == ‘R‘) {
			qs[i].tp = 3;
			while(isalpha(tc)) tc = Getchar();
		}
	}

	for(int i = 1; i <= n; i++) pa[i] = i, siz[i] = 1;
	for(int i = 1; i <= m; i++) {
		if(qs[i].tp == 3) continue;
		if(qs[i].tp == 1) {
			Union(qs[i].a, qs[i].b, i);
			if(i < m && qs[i+1].tp == 3) Del(cnt--), ans[i+1] = yes[cnt] ? sum[cnt] : 0;
		}
		if(qs[i].tp == 2) {
			int k = qs[i].a;
			if(i < m && qs[i+1].tp == 3) {
				ans[i+1] = ans[i-1];
				ans[i] = yes[cnt-k] ? sum[cnt-k] : 0;
			}
			else {
				for(int j = cnt; j >= cnt - k + 1; j--) Del(j);
				cnt -= k;
				ans[i] = yes[cnt] ? sum[cnt] : 0;
			}
		}
	}

	for(int i = 1; i <= m; i++) printf("%lld\n", ans[i]);

	return 0;
}
时间: 2024-08-27 03:58:17

【UER #1】[UOJ#12]猜数 [UOJ#13]跳蚤OS [UOJ#14]DZY Loves Graph的相关文章

[UOJ 12]猜数

Description Input Output Sample Input1 1 1 4 Sample Output1 4 5 Sample Explanation1 Sample Input2 12 8 Sample Output2 8 10 HINT 题解 此题巨坑无比.不要用unsigned/cin. 其次a,b是g的倍数的意思是"对于输入的g,a,b一定要是g的倍数",而不是"对于所有a,b,输入的g满足a,b是g的倍数"(这种理解其实直接就是g=1,而输入

20.10 for循环 20.11/20.12 while循环 20.13 break跳出循环 20.14 continue结束本次循环 20.15 exit退出整个脚本

20.10 for循环 ?语法:for 变量名 in 条件; do -; done ? 案例1 1+2+3..+100的和 #!/bin/bash sum=0 for i in `seq 1 100` // seq 1到100个数字 do sum=$[$sum+$i] echo $i done echo $sum sum 第一次作为变量的时候,是0:当进入for循环里面的时候,每运算一次,sum变量就会改变一次,直至$i 结束:最后输出结果 $sum ? 案例2 文件列表循环 #!/bin/ba

模拟算法_掷骰子游戏&amp;&amp;猜数游戏

模拟算法是用随机函数来模拟自然界中发生的不可预测的情况,C语言中是用srand()和rand()函数来生成随机数. 先来介绍一下随机数的生成: 1.产生不定范围的随机数 函数原型:int rand() 产生一个介于0~RAD_MAX间的整数,其具体值与系统有关系.Linux下为2147483647.我们可以在include文件夹中的stdlib.h中可以看到(Linux在usr目录下,Windows在安装目录下) 1 #include<stdio.h> 2 #include<stdlib

BZOJ 2222: [Cqoi2006]猜数游戏【神奇的做法,傻逼题,猜结论】

2222: [Cqoi2006]猜数游戏 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 604  Solved: 260[Submit][Status][Discuss] Description 佳佳和明明玩一个猜数游戏.佳佳想一个1~n之间的整数,明明每次可以随便猜一个数.从第二次猜测起,佳佳告诉明明本次猜测的数和上次猜测的数相比哪个更接近.B表示本次猜测的数更接近,W表示上次猜测的数更接近.如果两次猜测的接近程度一样,则既可回答B也可回答W.

CF 576A 猜数

A给出一个数x,B每次猜一个y,A回答B,x是否可以被y整除,求出要猜的最小次数和需要猜的数. 枚举每个素数p,可以知道如果p^k<=n,则p^k一定需要选 Sample test(s)input4output32 4 3 input6output42 4 3 5 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # i

猜数游戏,随机产生一个数字(0-9),自己看几次能出来,并且给出提示。

1 /* 2 * 猜数游戏,随机产生一个数字(0-9),自己看几次能出来,并且给出提示. 3 * */ 4 import java.util.Random; 5 import java.util.Scanner; 6 7 public class WhileTest{ 8 public static void main(String args[]){ 9 10 Scanner sc = new Scanner(System.in); 11 Random ran = new Random(); 1

1536 不一样的猜数游戏

1536 不一样的猜数游戏 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 瓦斯亚和皮台亚在玩一个简单的游戏.瓦斯亚心中想一个整数x,它是1到n之间的整数.然后皮台亚尝试着猜这个数字. 皮台亚每次问一个形如这样的问题:这个x是y的倍数吗? 这个游戏的流程是这样的:首先皮台亚把所有他想问的形如上述的问题都问出来(当然他也可以不问任何问题),然后瓦斯亚针对每一个问题给出yes或no的答案.最后皮台亚根据这些问题推断出瓦斯亚心中所想

LintCode 666. 猜数游戏 II

我们正在玩猜数游戏, 游戏内容如下:我在 1到 n 的范围内选择一个数作为待猜的数, 你需要来猜这个数,每次你猜错的时候, 我会告诉你我选择的这个数是比你说的数要高还是低, 但是, 当你猜这个数为 x 并且猜错的时候你需要支付 $x. 当你猜到我选择的数时, 你将赢得这场游戏 样例给出 n = 10, 我选择待猜数为 8第一轮: 你猜测为 5, 我告诉你待猜的值要更大一些. 你需要支付 $5第二轮: 你猜测为 7, 我告诉你待猜的值要更大一些. 你需要支付 $7第三轮: 你猜测为 9, 我告诉你

8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下

8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下 # 8.10 shell 特殊符_cut命令 --- - * 任意个任意字符 - ?任意一个字符 -  井号#注释字符  写命令的时候前面加一个#,那么这条命令就不生效,包括shell脚本里面也是,前面加个#表示这一行不生效,可以加一些注释说明的文字 ``` <[email protected] ~># #ls a.txt <[email