完整版题目点这里 回头可能还会丢几个能测评的洛谷链接
G - Horse Drinks Water
题意
将军饮马问题 河变成一个直角边
思路
本场签到 两条射线选一个做对称就行 最后取最小值
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ld dis(ld x1,ld y1,ld x2,ld y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void solve()
{
ld a,b,c,d;
cin>>a>>b>>c>>d;
ld ans=min(dis(-a,b,c,d),dis(a,-b,c,d));
printf("%.15Lf\n",ans);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
I - Friends
题意
给定一个无向图 如果一个区间里面所有点都互相有边连接则称该区间为友好区间 问一共有多少友好区间
思路
对一个点而言 因为区间必须连续 所以从一个点往前找 只要有一个点找不到了后面的就都算不了了 后面的点找也找不了这个点前面了 所以类似昨天刚学完的莫队的思想 我们把给边的输入先做排列 先将所有边只看成大数字连小数字 同一个点连出去的我再按终点从大到小排序 记得还要额外存自己指向自己的边就可以了
代码
#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
#define qwq ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
LL read()
{
LL sum = 0, fl = 1;
int ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
fl = -1;
for (; isdigit(ch); ch = getchar())
sum = sum * 10 + ch - '0';
return sum * fl;
}
LL qpow(int a, int b, int p)
{ // 快速幂
LL s = 1;
while (b)
{
if (b & 1)
s = (LL)s * a % p;
a = (LL)a * a % p;
b >>= 1;
}
return s;
}
const int N = 2e6 + 10;
struct edge
{
LL u, v;
bool operator<(const edge &T) const
{
if (u != T.u)
return u < T.u;
else
return v > T.v;
}
} ed[N];
LL fa[N];
LL find(LL x)
{
if (x == fa[x])
return fa[x];
return fa[x] = find(fa[x]);
}
LL memo[N];
vector<LL> e[N];
int flag[N];
void solve()
{
LL n = read(), m = read();
for (int i = 1; i <= m; i++)
{
LL x = read(), y = read();
if (x < y)
swap(x, y);
ed[i] = {x, y};
}
for (int i = 1; i <= n; i++)
ed[m + i] = {i, i};
sort(ed + 1, ed + 1 + m + n);
for (int i = 1; i <= n; i++)
memo[i] = i;
LL last = 0;
LL memoidx = 1, memolast;
//printf("\n\n");
for (int i = 1; i <= m + n; i++)
{
LL u = ed[i].u, v = ed[i].v;
if (memoidx != u && flag[memoidx] == 0)
last = max(last,memolast);
memolast = v,memoidx = u;
// printf(" out %lld %lld %lld\n", u, v, last);
if (memo[u] == v)
{
memo[u]--;
// printf(" in1 %lld %lld %lld\n", u, v, last);
if (v <= last)
continue;
//printf(" in2 %lld %lld %lld\n", u, v, last);
e[u].push_back(v);
if (v == 1)
flag[u] = 1;
memolast--;
}
else
last = max(memo[u], last);
}
LL ans = 0;
for (int i = 1; i <= n; i++)
ans += e[i].size();
printf("%lld\n", ans);
}
int main()
{
solve();
return 0;
}
H- Yet Another Origami Problem
题意
任意次操作 每一次都可以选一个数把比他小的都对称翻过去或者比他大的对称翻过去 最小化给定数列的极差
思路
一开始的直觉是只要差值不是全一样那么一定能变0 被队友hack之后大胆guess求差值gcd然后就过了
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
ll n;
scanf("%lld",&n);
vector<ll> a(n);
for(ll i=0;i<n;i++) scanf("%lld",&a[i]);
sort(a.begin(),a.end());
ll gcd=0;
for(ll i=1;i<n;i++)
gcd=__gcd(gcd,a[i]-a[i-1]);
printf("%lld\n",gcd);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
C - Sort4
题意
给定一个排列 每次可以任选4个数随便交换位置 问最少操作多少次可以变成有序
思路
建图 在每一个连通块当中除了最后一组只能3个3个修改到正确的位置 如果连通块大小为2那就可以两个联通块凑一下节省一次
代码
#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
#define qwq ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
LL read()
{
LL sum = 0, fl = 1;
int ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
fl = -1;
for (; isdigit(ch); ch = getchar())
sum = sum * 10 + ch - '0';
return sum * fl;
}
LL qpow(int a, int b, int p)
{ // 快速幂
LL s = 1;
while (b)
{
if (b & 1)
s = (LL)s * a % p;
a = (LL)a * a % p;
b >>= 1;
}
return s;
}
const int N = 1e6 + 10;
LL p[N], sz[N];
// 初始化
// 返回x的祖宗节点+路径压缩
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
// 合并a和b所在的两个集合
void merge(LL a, LL b)
{
if(find(a)==find(b))
return;
sz[find(b)] += sz[find(a)];
p[find(a)] = find(b);
}
map<LL, int> vis;
void solve()
{
vis.clear();
LL n = read();
for (int i = 1; i <= n; i++)
{
p[i] = i;
sz[i] = 1;
}
for (int i = 1; i <= n; i++)
merge(i, read());
LL ans = 0, more = 0, cnt = 0;
for (int i = 1; i <= n; i++)
{
LL fa = find(i);
if (vis[fa])
continue;
vis[fa] = 1;
//printf("fa:%lld sz:%lld\n", fa, sz[fa]);
if (sz[fa] >= 4)
{
ans += sz[fa] / 3;
LL nowmore = sz[fa] % 3;
if (nowmore >= 2)
cnt++;
}
else if (sz[fa] == 3)
ans++;
else if (sz[fa] == 2)
cnt++;
}
printf("%lld\n", ans + (cnt + 1) / 2);
}
int main()
{
LL t = read();
while (t--)
solve();
return 0;
}