A - Collecting Coins
题意:给你四个数a,b,c,n;让你把n给个a,b,c三个数使a,b,c相等且n恰好分完
思路:找出a,b,c中最大的先将其他两个加到最大的,然后判断剩下的n是否能被3整除即可;
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T--){
int a[3],n;
for(int i = 0;i < 3;i++) cin >> a[i];
sort(a,a + 3);
int cha = a[2] - a[0] + a[2] - a[1];
cin >> n;
if(cha > n) puts("NO");
else if((n - cha)%3) puts("NO");
else puts("YES");
}
}
B - Collecting Packages
题意:给你n个点,让只能往上或者往右走,不能回头,让你判断能不能走完所有的点,如果能走完输出走的路径。
思路:按x排序,x相同按y排序,依次走过这几个点即可。
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
struct node{
int x,y;
bool operator <(const node &a)const{
if(x == a.x) return y < a.y;
return x < a.x;
}
}a[maxn];
string s;
int main(){
int T;cin >> T;
while(T--){
int n;cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i].x >> a[i].y;
sort(a + 1,a + 1 + n);
s.clear();
int sx = 0,sy = 0;
int flag = 0;
for(int i = 1;i <= n;i++){
while(a[i].x > sx) sx++,s += 'R';
if(a[i].y < sy){
flag = 1;break;
}
while(a[i].y > sy) sy++,s += 'U';
}
if(flag == 1)puts("NO");
else {
puts("YES");cout << s <<"\n";
}
}
}
C - Product of Three Numbers
题意:给你一个数n,让你分解成三个不同的数的乘积形式,若不能输出no。
思路:考虑分解出两个数,然后用除法求出第三个数判断是否与前两个数相同即可。
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
vector<int>ans;
int main(){
int T;cin >> T;
while(T--){
ans.clear();
int n;cin >> n;
int num = 0;
for(int i = 2;i * i <= n;i++){
if(n % i == 0) n /= i,ans.push_back(i),num++;
if(num == 2) break;
}
if(num < 2) printf("NO\n");
else if(ans[0] != n && ans[1] != n) puts("YES"),printf("%d %d %d\n",ans[0],ans[1],n);
else printf("NO\n");
}
}
D - MEX maximizing
题意:给你q次操作,x为每层的个数。每次操作在集合中加入一个数n,你可以对n进行任意次+n或-n操作,问这个集合中不存在的最小的整数是多少。
思路:
以下提供两种思路:
1:
用线段树维护我最多可以凑出多少层,线段树查询第一个不满足该层的是哪个即为ans,答案就是 层数*x+ans-1;
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 4e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
int a[maxn << 2];
void update(int rt,int l,int r,int s){
if(l == r) {
a[rt]++;return;
}
int mid = l + r >> 1;
if(s <= mid) update(rt << 1,l,mid,s);
else update(rt<< 1 | 1,mid + 1,r, s);
a[rt] = min(a[rt << 1],a[rt << 1 | 1]);
}
int query(int rt,int l,int r,int sum){
if(l == r) return l;
int mid = l + r >> 1;
if(a[rt << 1] == sum) return query(rt << 1,l,mid ,sum);
else return query(rt << 1 | 1,mid + 1,r,sum);
}
int main(){
int x,q;cin >> q >> x;
while(q--){
int n;cin >> n;
update(1,1,x,n % x + 1);
int ans = query(1,1,x,a[1]);
cout << a[1] * x + ans - 1 << "\n";
}
}
2:
我们只需要保存集合中%x为0 ~ x-1的个数,用一个tmp去记录答案。当你的a[tmp%x]不为0的时候,你的tmp就可以++,同时就说明你这个a[tmp%x]已经被用掉一个了,就需要减去一个了。
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 4e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
int has[maxn];
int main(){
int q,x;cin >> q >> x;
int ans = 0;
while(q--){
int n;scanf("%d",&n);
has[n % x]++;
while(has[ans % x]){
has[ans % x]--;
ans++;
}
printf("%d\n",ans);
}
}
E - Obtain a Permutation
题意:给你一个n*m的矩阵,你可以进行两个操作:
1:对一列向上一个单位,第一个放到最后一个。
2:改变某个位置上数的值。
问你需要操作几次才能使矩阵按照顺序排列好。
思路:
首先它具有独立性,我不会和行有关,只会与列相关。于是我们就按列去考虑。考虑暴力的方法,我们用一个cnt数组去记录该数要以列第几个数作为第一行时不需要以动。然后对于第i个数作为开头的花费就是n - cnt[i] + i;对i进行遍历就可以求出每行的最小花费即可。
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
int ans = 0;
int main(){
int n, m;
cin >> n >> m;
vector<vector<int>> a(n, vector<int>(m));
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++) {
cin >> a[i][j];
a[i][j]--;
}
}
for(int j = 0;j < m;j++){
vector<int>cnt(n);
for(int i = 0;i < n;i++){
if(a[i][j] % m == j && a[i][j] < m * n){
cnt[(i - a[i][j] / m + n) % n]++;
}
}
int minn = n;
for(int i = 0;i < n;i++){
minn = min(minn,n - cnt[i] + i);
}
ans += minn;
}
cout << ans << endl;
}
F. Three Paths on a Tree
题意:表述很简单,给你一颗树,让你找出3个点使这三个任意两点相连覆盖的点的并集最大。
思路:首先这三个点必有两个点是树的直径,直径的求法为随便找一个点bfs到最远的为直径的一个端点。用这个端点再bfs出来的最远的点即为圆的另一个端点。我们在bfs的同时也可以把这两个端点到每个其他点的距离也处理出来,然后我们对n个点(出去两个端点)进行遍历,答案为(树的直径+该点到两个端点的距离)/ 2,然后求最大值输出即可。
#include<bits/stdc++.h>
#define accept return 0
#define mes(a, b) memset(a, b, sizeof a)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e5 + 5;
const int maxm = 1e5 + 10;
const int mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-6;
using namespace std;
int pos;
vector<int>mp[maxn];
int dis1[maxn],dis2[maxn],dis[maxn],vis[maxn];
void bfs(int x){
mes(vis,0);mes(dis,0);
pos = x;vis[x] = 1;dis[x] = 0;
queue<int>q;q.push(x);
while(!q.empty()){
int u = q.front();q.pop();
for(auto it : mp[u]){
if(vis[it]) continue;
vis[it] = 1;
dis[it] = dis[u] + 1;
q.push(it);
if(dis[it] > dis[pos]) pos = it;
}
}
}
int main(){
int n;scanf("%d",&n);
for(int i = 1;i < n;i++){
int u,v;scanf("%d %d",&u,&v);
mp[u].push_back(v);mp[v].push_back(u);
}
int a,b,c;
bfs(1);a = pos;
bfs(pos);b = pos;
for(int i = 1;i <= n;i++) dis1[i] = dis[i];
bfs(pos);
for(int i = 1;i <= n;i++) dis2[i] = dis[i];
c = 0;
for(int i = 1;i <= n;i++){
if(dis1[i] + dis2[i] > dis1[c] + dis2[c] && i != a && i != b) c = i;
}
printf("%d\n%d %d %d\n",(dis2[a] + dis1[c] + dis2[c]) / 2,a,b,c);
}