链接:https://ac.nowcoder.com/acm/contest/12222/A
来源:牛客网
题目描述
Forsaken有一个有趣的数论函数。对于任意一个数xx,f(x)f(x)会返回xx的最小质因子。如果这个数没有最小质因子,那么就返回0。
现在给定任意一个nn,Forsaken想知道\sum_{i = 1}^{n}{f(i)}∑
i=1
n
f(i)的值。
输入描述:
一个整数nn。
输出描述:
一个整数代表上面的求和式的值。
示例1
输入
复制
4
输出
复制
7
备注:
1 \leq n \leq 3e71≤n≤3e7
找到每个数的最小的质数,素数筛法即可
/* _
_ooOoo_
o8888888o
88" . "88
(| -_- |)
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
===========`-.`___`-.__\ \___ /__.-'_.'_.-'================
Please give me AC.
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 3e7 + 10;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
bool st[N];
int primes[N], cnt;
int ans;
int a[N];
int n;
void get_primes(int n){
for (int i = 2; i <= n; i ++){
if (!st[i]){
primes[cnt ++] = i;
a[i] = i;
}
for (int j = 0; primes[j] * i <= n; j ++){
st[primes[j] * i] = true;
a[primes[j] * i] = primes[j];
if (i % primes[j] == 0){
break;
}
}
}
}
signed main(){
cin >> n;
get_primes(n);
for (int i = 2; i <= n; i ++) ans += a[i];
cout << ans << endl;
return 0;
}
Forsaken喜欢字符串
链接:https://ac.nowcoder.com/acm/contest/12222/B
来源:牛客网
题目描述
Forsaken有一堆字符串,他发现每个字符串都有自己的价值。比如说对于一个字符串SS,长度为|S|∣S∣。如果存在其他字符串S_iS
i
,长度为|S_i|∣S
i
∣。那么字符串SS能获得的价值为f(i) = \sum_{l_1=1}{|S|}\sum_{r_1=l_1}{|S|}\sum_{l_2=1}{|S_i|}\sum_{r_2=l_2}{|S_i|}S[l_1,r_1] =S_i[l_2,r_2]f(i)=∑
l
1
=1
∣S∣
∑
r
1
=l
1
∣S∣
∑
l
2
=1
∣S
i
∣
∑
r
2
=l
2
∣S
i
∣
[S[l
1
,r
1
]=S
i
[l
2
,r
2
]](r
1
−l
1
+1),[S[l_1,r_1] =S_i[l_2,r_2]][S[l
1
,r
1
]=S
i
[l
2
,r
2
]]是指对于SS的子串[l_1,r_1][l
1
,r
1
]与S_iS
i
的子串[l_2,r_2][l
2
,r
2
]相等时为1,否则为0。
现在Forsaken有nn个串并且每个串的长度都是kk,现在他会问你qq个问题,对于每个问题,你需要回答对于串S_xS
x
的所有长度为lenlen的子串的价值之和(不包括S_iS
i
自身的子串)。
输入描述:
第一行两个整数n,kn,k。
接下来nn行每行一个长度为kk且都是小写字母的字符串
第n+2n+2行是一个整数qq。
接下来qq行每行两个整数x,lenx,len。
输出描述:
qq行整数分别对应每个询问的答案
示例1
输入
复制
3 2
aa
aa
aa
1
3 1
输出
复制
8
备注:
1\leq n\leq5e41≤n≤5e4
1\leq k \leq 51≤k≤5
1\leq q \leq 1e41≤q≤1e4
1\leq x \leq n1≤x≤n
1\leq len \leq k1≤len≤k
现预处理出所有的字符串出现的次数,然后再求每个字符串的长度在剩下的字符串分别出现了多少次,再贡献累加即可
/* _
_ooOoo_
o8888888o
88" . "88
(| -_- |)
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
===========`-.`___`-.__\ \___ /__.-'_.'_.-'================
Please give me AC.
*/
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 5e4 + 100;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
unordered_map<string, int> mp, mp_temp;
int n, k;
string s[N];
signed main(){
ios;
cin >> n >> k;
for (int i = 1; i <= n; i ++){
cin >> s[i];
for (int j = 0; j < k; j ++){
for (int len = 1; j + len - 1 < k; len ++){
string temp = s[i].substr(j, len);
mp[temp] ++;
}
}
}
int q;
cin >> q;
int ans = 0;
while(q --){
ans = 0;
mp_temp.clear();
int x, len;
cin >> x >> len;
for (int i = 0; i + len - 1 < k; i ++){
string temp = s[x].substr(i, len);
mp_temp[temp] ++;
}
for (auto it = mp_temp.begin(); it != mp_temp.end(); it ++){
ans += (mp[it -> first] - mp_temp[it -> first]) * (it -> second) * len;
}
cout << ans << endl;
}
return 0;
}
Forsaken给学生分组
链接:https://ac.nowcoder.com/acm/contest/12222/C
来源:牛客网
题目描述
Forsaken有nn个学生,每个学生都有一个能力值a_ia
i
,为了方便管理,Forsaken决定将nn个学生分成kk组。
Forsaken认为如果一个小组有一个能力在该小组极其突出的学生,这个小组就比较容易管理。我们定义对于team_iteam
i
来说,这个小组的管理方便度f(i) = max(a_j \in team_i) - min(a_j \in team_i)f(i)=max(a
j
∈team
i
)−min(a
j
∈team
i
)。Forsaken现在想知道max(\sum_{i=1}^{k}f(i))max(∑
i=1
k
f(i))。
输入描述:
第一行两个整数分别为n,kn,k。
第二行nn个数分别代表a_1,a_2…a_na
1
,a
2
…a
n
。
输出描述:
一个整数表示最大的管理方便度之和。
示例1
输入
复制
5 1
10 6 2 7 9
输出
复制
8
备注:
1 \leq n \leq 1e51≤n≤1e5
1 \leq k \leq n1≤k≤n
1 \leq a_i \leq 1e91≤a
i
≤1e9
答案可以二分,还需要判断的是最多有多少对可以两两构成,然后特殊判断即可
/* _
_ooOoo_
o8888888o
88" . "88
(| -_- |)
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
===========`-.`___`-.__\ \___ /__.-'_.'_.-'================
Please give me AC.
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e5 + 10;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int a[N];
int n;
int k;
bool check(int mid){
int cnt = 0;
int cha = 2 * k - n;
if (cha <= 0) cnt = k;
else cnt = (k - cha);
int res = 0;
if (cnt >= 1){
for (int i = 1, j = n; i <= cnt; i ++, j --){
res += (a[j] - a[i]);
}
}
return res >= mid;
}
signed main(){
ios;
cin >> n >> k;
for (int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + 1 + n);
int l = 0, r = 1e18;
while(l < r){
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l << endl;
return 0;
}
Forsaken喜欢正方形
链接:https://ac.nowcoder.com/acm/contest/12222/D
来源:牛客网
Forsaken特别喜欢正方形,现在他有二维平面的四个整点。如果四个整点可以直接形成一个正方形,输出"wen"。如果可以通过对其中一个点进行一次轻微的调整使得四个整点形成一个正方形,输出“hai xing”,轻微的调整是指如果当前整点坐标为(x,y)(x,y),那么我们可以把这个点变成(x+1,y),(x-1,y),(x,y+1),(x,y-1)(x+1,y),(x−1,y),(x,y+1),(x,y−1)中的一种。否则如果都不行,输出“wo jue de bu xing”。
输入描述:
输入有四行,每行一个二维坐标(x,y)(x,y)
输出描述:
按题面给定输出。
示例1
输入
复制
0 0
0 1
1 1
1 0
输出
复制b
wen
备注:
0 \leq x,y \leq 1000≤x,y≤100
爆搜即可,需要注意的是在判断是否为正方形的过程中不能改变原来的数组,第二个是判断是否是正方形不一定是特殊的,需要判断是否三条边相等,然后是否斜边是直角边的根号2倍
/* _
_ooOoo_
o8888888o
88" . "88
(| -_- |)
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
===========`-.`___`-.__\ \___ /__.-'_.'_.-'================
Please give me AC.
*/
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 100;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
bool flag = false;
struct Node{
int x, y;
bool operator<(const Node &W)const{
if (x == W.x) return y < W.y;
return x < W.x;
}
}node[N], node2[N];
int get_dist(int i, int j){
return (node2[i].x - node2[j].x) * (node2[i].x - node2[j].x) + (node2[i].y - node2[j].y) * (node2[i].y - node2[j].y);
}
bool check(){
for (int i = 1; i <= 4; i ++){
node2[i] = node[i];
}
set<int> ss;
for (int i = 1; i <= 4; i ++){
for (int j = 1; j <= 4; j ++){
if (i == j) continue;
ss.insert(get_dist(i, j));
}
}
if (ss.size() != 2) return false;
int temp1, temp2;
for (auto it = ss.begin(); it != ss.end(); it ++){
if (it == ss.begin()) temp1 = *it;
else temp2 = *it;
}
if (temp1 * 2 - temp2 != 0) return false;
return true;
}
void dfs(int u){
if (u >= 5){
if (check()) flag = true;
return;
}
//cout << node[u].x << "----" << node[u].y << endl;
node[u].x += 1;
dfs(u + 1);
//cout << node[u].x << "----" << node[u].y << endl;
node[u].x -= 1;
node[u].x -= 1;
dfs(u + 1);
//cout << node[u].x << "----" << node[u].y << endl;
node[u].x += 1;
node[u].y += 1;
dfs(u + 1);
//cout << node[u].x << "----" << node[u].y << endl;
node[u].y -= 1;
node[u].y -= 1;
dfs(u + 1);
// cout << node[u].x << "----" << node[u].y << endl;
node[u].y += 1;
//cout << node[u].x << "----" << node[u].y << endl;
dfs(u + 1);
}
signed main(){
for (int i = 1; i <= 4; i ++){
cin >> node[i].x >> node[i].y;
}
sort(node + 1, node + 1 + 4);
if (check()) cout << "wen" << endl;
else{
dfs(1);
if (flag) cout << "hai xing" << endl;
else cout << "wo jue de bu xing" << endl;
}
return 0;
}
/*
0 0
1 0
0 1
1 2
*/
Forsaken的三维数点
链接:https://ac.nowcoder.com/acm/contest/12222/G
来源:牛客网
题目描述
Forsaken现在在一个三维空间中,空间中每个点都可以用(x,y,z)(x,y,z)表示。突然,三维空间的主人出现了,如果Forsaken想要继续在三维空间中呆下去,他就必须回答三维空间主人的问题。
主人会在空间中坐标为(x,y,z)(x,y,z)处加一点能量值,当他加了一定的次数之后,他会问Forsaken一个问题:如果坐标(0,0,0)(0,0,0)为球心,那么至少需要多大的半径才能使得球内的能量值总和大于或者等于kk,在这里,半径为00也是可以的。这对于Forsaken来说实在是太难了,因此他把这个问题交给了你。
输入描述:
第一行一个nn表示操作的次数。
接下来每行首先一个整数opop表示操作的种类。
如果op = 1op=1,接下来33个整数x,y,zx,y,z表示能量值增加的坐标。
如果op =2op=2,接下来一个整数kk表示要求的能量值总和。
输出描述:
对于每个op=2op=2的操作,输出一个整数表示球的半径。(数据保证至少有一个22操作)
如果没有满足答案的半径,输出-1−1。
示例1
输入
复制
2
1 1 1 1
2 1
输出
复制
2
备注:
1 \leq n \leq 2e51≤n≤2e5
1 \leq op \leq 21≤op≤2
-1e5 \leq x, y, z \leq 1e5−1e5≤x,y,z≤1e5
0\leq k \leq 2e50≤k≤2e5
可以考虑的到修改的话在距离圆心的那个距离的位置上加1,但是如何查找,维护的是什么,我们需要维护的是区间的和,然后查找的话,首先从1号节点开始找,看她左儿子的和是否大于等于k,大于的话再向左走,否则的话向右走,最后在一个结点的时候就是答案。需要注意的是,有可能坐标为0,建树的时候可以建最大值,如果要查找的树比1号点的和还大的话,那么答案就是-1
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 100;
struct Segment_tree
{
int l, r;
int sum;
} tr[N * 4];
int n, m;
int a[N];
void pushup(Segment_tree &u, Segment_tree &l, Segment_tree &r)
{
u.sum = l.sum + r.sum;
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
if (l != r) tr[u] = {l, r, 0};
else
{
tr[u] = {l, r, 0};
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int d)
{
if (tr[u].l == l && tr[u].r == l)
{
tr[u].sum += d;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(u << 1, l, d);
else if (l > mid) modify(u << 1 | 1, l, d);
pushup(u);
}
int query(int u, int k)
{
if (tr[u].l == tr[u].r) return tr[u].l;
else if (tr[u << 1].sum >= k) return query(u << 1, k);
else return query(u << 1 | 1, k - tr[u << 1].sum);
}
int main()
{
ios::sync_with_stdio(false);
cin >> n;
build(1, 0, N); //注意
while(n --){
int op;
cin >> op;
if (op == 1){
long long x, y, z;//注意
cin >> x >> y >> z;
int len = (int)ceil(sqrt(x * x + y * y + z * z));
modify(1, len, 1);
}
else {
int k;
cin >> k;
if (k > tr[1].sum){ //注意
cout << "-1" << endl;
continue;
}
cout << query(1, k) << endl;
}
}
return 0;
}
链接:https://ac.nowcoder.com/acm/contest/12222/H
来源:牛客网
题目描述
众所周知,最小生成树是指使图中所有节点连通且边权和最小时的边权子集。
不过最小生成树太简单了,我们现在来思考一个稍微复杂一点的问题。
现在给定一个nn个点,mm条边的图,每条边e_ie
i
都有一个权值w_iw
i
。定义删除一条边e_ie
i
的代价为w_iw
i
,并且你可以对这个图执行任意次删边操作。
设这个图的最小生成树权值和为sumsum,定义一个图的最小生成树是独一无二的当且仅当这个图的边集中没有除最小生成树外的其他子集能满足权值和为sum且使得所有点连通。一个图刚开始可能没有独一无二的最小生成树,现在你可以删除一些边,使得剩下的边的最小生成树大小依然为sumsum并且这个图的最小生成树是独一无二的。
现在我们想要知道删除的边的权值和最小是多少?
输入描述:
第一行输入为nn和mm,表示这个图的点数和边数。
接下来mm行,每行三个值u_iu
i
,v_iv
i
,w_iw
i
,分别代表每条边的两个端点和边权。
输出描述:
一个整数,代表删除的边的最小权值和。
示例1
输入
复制
1 0
输出
复制
0
备注:
1 \leq n\leq 2e51≤n≤2e5
n - 1 \leq m\leq 2e5n−1≤m≤2e5
1 \leq u_i, v_i \leq n1≤u
i
,v
i
≤n
1 \leq w_i \leq1e91≤w
i
≤1e9
一条边可以替换最小生成树的边的话,有什么性质,就是说把某一条边删了,可以换这条边上去,这条边一定和删的那条边是相等的,如果不是相等的,如果更大,那么就不是了,如果更小,为什么当选选择删除的那条便呢,既然相等,并且删了用这条边还好使唤,说明当初在加边的时候,如果没有要删的那条边,这条边就上去了,为什么没上去了,就是因为前面那条边让这条边的两端变成一个集合了,所以我们只需要看相等的边并且之前没有加进集合一次性加进来,然后再把是最小生成树的边减去即可‘’‘
/* _
_ooOoo_
o8888888o
88" . "88
(| -_- |)
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
===========`-.`___`-.__\ \___ /__.-'_.'_.-'================
Please give me AC.
*/
#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(int x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 2e5 + 100;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
struct Edge{
int a, b, w;
bool operator<(const Edge &W)const{
return w < W.w;
}
}edge[N];
int p[N];
int n, m;
int find(int x){
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
//突破口:哪些边可以替代
signed main(){
ios;
cin >> n >> m;
for (int i = 1; i <= m; i ++){
int a, b, w;
cin >> a >> b >> w;
edge[i] = {a, b, w};
}
for (int i = 1; i <= n; i ++) p[i] = i;
sort(edge + 1, edge + 1 + m);
int res = 0;
for (int i = 1; i <= m; i ++){
int a = edge[i].a, b = edge[i].b, w = edge[i].w;
int j = i;
while(edge[j].w == w && j <= m) j ++;
j --;
for (int k = i; k <= j; k ++){
int a = edge[k].a, b = edge[k].b, w = edge[k].w;
int pa = find(a), pb = find(b);
if (pa != pb){
res += w;
}
}
for (int k = i; k <= j; k ++){
int a = edge[k].a, b = edge[k].b, w = edge[k].w;
int pa = find(a), pb = find(b);
if (pa != pb){
p[pa] = pb;
res -= w;
}
}
i = j;
}
cout << res << endl;
return 0;
}