zoukankan      html  css  js  c++  java
  • 【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说道:“我可以告诉你正整数 gl的值,我保证 ab=gl=na,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
    ", 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. 首先,随便写出两个文件路径 st
    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
    ", 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('
    ');
    	}
    	
    	return 0;
    }
    

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

    试题描述

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

    1. Add a b: 表示在 ab 之间连了一条长度为 i 的边(注意,i 是操作编号)。保证 1a,bn
    2. Delete k: 表示删除了当前图中边权最大的k条边。保证 k 一定不会比当前图中边的条数多。
    3. Return: 表示撤销第 i1 次操作。保证第 1 次操作不是 Return 且第 i1 次不是 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

    戳我下载

    数据规模及约定

    n3×105, m5×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
    ", ans[i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    年纪大了,要学会控制自己的欲望
    java为什么要用类型擦除实现泛型?--c++,java,c# 的泛型是如何实现的
    面向对象:类的成员---只是特定(类的)命名空间的全局变量(函数)而已
    人的意志与自然法则—人的意志与人造事物
    所有的思考都有两个目的:建模降熵
    控制论、系统论与熵
    秩序(也常简称为序)是系统的本质特征之一
    控制论:基于全局信息和整体目标、整体规则的系统结构和状态维护
    人类社会的全部认识成果可以概括为三大领域的科学,即自然科学、社会科学和思维科学
    “逻辑”的古希腊词源
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5450530.html
Copyright © 2011-2022 走看看