标签:开头 距离 端点 packages mat 过程 red def const
注意\(n\)可能不够用的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, b, c, n;
void solve()
{
cin >> a >> b >> c >> n;
int mx = max(max(a, b), c);
int mi = min(min(a, b), c);
int s = a+b+c;
int m = s - mx - mi;
n -= (mx - mi);
n -= (mx - m);
if(n < 0){
puts("NO");
return;
}
if(n % 3 == 0) puts("YES");
else puts("NO");
}
int main()
{
int T = 1;
scanf("%d", &T);
while(T--) solve();
return 0;
}
直接模拟这个过程就好了,注意字典序最小的方案。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 10;
int n;
//只能上和右
struct Node{
int x, y;
}p[maxn];
bool cmp(Node a, Node b){
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
void solve()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
sort(p+1, p+1+n, cmp);
for(int i = 1; i < n; i++)
{
if(p[i].y > p[i+1].y && p[i].x != p[i+1].x)
{
puts("NO");
return;
}
}
puts("YES");
string ans = "";
for(int i = 0; i < n; i++)
{
int x1 = p[i].x, y1 = p[i].y;
int x2 = p[i+1].x, y2 = p[i+1].y;
int d1 = x2 - x1;
int d2 = y2 - y1;
while(d1) ans += 'R', d1--;
while(d2) ans += 'U', d2--;
}
cout << ans << endl;
}
int main()
{
int T = 1;
scanf("%d", &T);
while(T--) solve();
return 0;
}
枚举因数,看看能不能成。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
int n; cin >> n;
vector<int> ans;
int t = n;
for(int i = 2; i <= n/i; i++)
{
if(t % i == 0)
{
ans.push_back(i);
t = t / i;
}
if(t == 1) break;
}
if(ans.size() == 1 || ans.size() == 0)
{
puts("NO");
return;
}
if(ans.size() == 2)
{
int t = ans[0]*ans[1];
if(n % t == 0 && n/t != ans[0] && n/t != ans[1])
{
puts("YES");
printf("%d %d %d\n", ans[0], ans[1], n/t);
return;
}
else
{
puts("NO");
return;
}
}
puts("YES");
int t1 = ans[0], t2 = ans[1];
int t3 = n/(t1*t2);
printf("%d %d %d\n", t1, t2, t3);
}
int main()
{
int T;
scanf("%d", &T);
while(T--) solve();
return 0;
}
根据贪心的思路我们可以发现答案一定是递增的,所以我们就直接把所有的点都减到不能减为止,然后答案可以变大的时候用他们来做贡献。
其实可以不用\(unordered\_map\),可以直接用数组来维护一下...
#include<bits/stdc++.h>
using namespace std;
const int maxn = 4e5 + 10;
int q, x;
int main()
{
scanf("%d%d", &q, &x);
vector<int> a;
unordered_map<int, int> mp;
int ans = 0;
while(q--)
{
int num;
scanf("%d", &num);
mp[num % x]++;
while(mp[ans]) ans++;
while(mp[ans%x] > 1)
{
mp[ans%x]--;
ans++;
}
printf("%d\n", ans);
}
return 0;
}
题意也就是用最少的操作次数使得矩阵每个元素\(a(i,j)=(i-1)m+j\)。
分析一下的话可以发现,每一列其实是独立的,所以最终答案一定是每一列的答案相加。
考虑第\(j\)列,最终第\(j\)列的元素就为\(j,j+m,j+2m,...,j+(n-1)m\)。
对于给出的第\(j\)列数字,可以枚举谁作为最高位,从而来计算答案。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
vector<int> a[maxn], b[maxn];
int n, m;
int vis[maxn], add[maxn<<1];
int main()
{
scanf("%d%d", &n, &m);
int cnt = 0;
for(int i = 1; i <= n; i++)
{
a[i].resize(m+1);
b[i].resize(m+1);
for(int j = 1; j <= m; j++)
{
scanf("%d", &a[i][j]);
b[i][j] = ++cnt;
}
}
long long ans = 0;
for(int j = 1; j <= m; j++)
{
for(int i = 1; i <= n; i++) vis[b[i][j]] = i;
for(int i = 1; i <= n; i++)
{
if(vis[a[i][j]]) //如果这个数本应该属于这个序列中
{
int t = vis[a[i][j]];
if(t == i) add[1]++, add[n+1]++; //正好在位置上
//放到该放到的位置上
else if(i > t) add[1+i-t]++;
else add[1+n+i-t]++;
}
}
int tmp = 0, mi = n;
//枚举开头的位置
for(int l = 1; l <= n; l++)
{
tmp = add[l];
//tmp 不需要变化的元素
//本次需要的操作=n-不需要变化的元素+把它们shift到最高位
mi = min(mi, n-tmp+(l-1));
} ans += mi;
for(int i = 1; i <= 2*n; i++) add[i] = 0;
for(int i = 1; i <= n; i++) vis[b[i][j]] = 0;
} cout << ans << endl;
return 0;
}
首先可以确定的是,其中的两个点一定在直径的两个端点上。
第三个点要怎么确定呢?
设\(len(a,b)\)表示\(a\)到\(b\)的距离,那么答案就是\(\frac{len(a,b)+len(b,c)+len(a,c)}{2}\)。
所以我们找\(len(a,c)+len(b,c)\)最大就行了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n;
int head[maxn], nex[maxn<<1], ver[maxn<<1], edge[maxn<<1], tot;
inline void add_edge(int x, int y){
ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
edge[tot] = 1;
}
int vis[maxn];
int sum[maxn];
int bfs(int x)
{
memset(vis, 0, sizeof(vis));
queue<int> q;
q.push(x);
int t;
while(q.size())
{
t = q.front(); q.pop();
for(int i = head[t]; i; i = nex[i])
{
int y = ver[i];
if(!vis[y] && y != x)
{
q.push(y);
vis[y] = vis[t] + 1;
}
}
} return t; //bfs两段性保证t最远
}
int main()
{
scanf("%d", &n);
for(int i = 1, x, y; i <= n-1; i++)
{
scanf("%d%d", &x, &y);
add_edge(x, y); add_edge(y, x);
}
int x = bfs(1), y = bfs(x), ans = 0, z;
//此时的vis数组中存着每个点离x的距离
//sum数组中存着len(x,y)+len(x,i)
for(int i = 1; i <= n; i++)
sum[i] = vis[y] + vis[i];
bfs(y); //vis数组中存着每个点离y的距离
for(int i = 1; i <= n; i++)
{
//sum中存着len(x,y)+len(x,i)+len(y,i)
sum[i] += vis[i];
if(i != x && i != y && sum[i] > ans)
{
ans = sum[i];
z = i;
}
}
printf("%d\n%d %d %d\n", ans/2, x, y, z);
return 0;
}
Codeforces Round #615(Div.3)解题报告
标签:开头 距离 端点 packages mat 过程 red def const
原文地址:https://www.cnblogs.com/zxytxdy/p/12236772.html