Codeforces Round #756 (Div. 3)
A. Make Even
思路:如果末尾是偶数,不需要操作;如果开头是偶数,一次操作,即全翻转;如果开头和末尾都是 奇数,判断里面是否有偶数,如果没有,无法操作,如果有,需要两次操作。
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i, n) for (int i = 0; i < n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
string str;
int a[N];
void solve()
{cin>>str;int len = str.length();int ff = -1;//无法操作int kk = 0;for (int i=0;i<len;i++){a[i] = str[i]-'0';if (a[i]%2==0) kk = 1;}if (a[0]%2==0) ff = 1;//如果开头是偶数if (a[len-1]%2==0) ff = 0;//如果末尾是操作,更优if (ff==-1&&kk) ff = 2;//如果末尾和开头都不是偶数,中间有偶数cout<<ff<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
B. Team Composition: Programmers and Mathematicians
思路:先看总人数能组成多少队,然后再限制。
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i, n) for (int i = 0; i < n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
string str;
int a[N];
void solve()
{int a,b;cin>>a>>b;int cou = (a+b)/4;//最多组成多少队cou = min(cou,min(a,b));//限制判断cout<<cou<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
C. Polycarp Recovers the Permutation
思路:首先,最大的数应该在最外面,不是最左边就是最右边。其次,如果它在最左边,那就只要一开始它在最右边,就可以控制其他数反向输出,右边同理。
example : 5 3 2 4 1 → 1 4 2 3 5
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i) for (int i = 1; i <= n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
int a[N];
void solve()
{int n;cin>>n;for (int i=0;i<n;i++){cin>>a[i];}if (a[0]!=n&&a[n-1]!=n) {cout<<-1<<endl;return;}for (int i=n-1;i>=0;i--){cout<<a[i]<<" ";}cout<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
D. Weights Assignment For Tree Edges
题目意思:先给出每个数父节点。下一行给出每一位dist的大小排序(我觉得这里有点难读)。
example : [3 1 2 5 4] → 节点三是最小的,其次是一,然后二,五,四。
思路:先判断最小的是不是父节点。然后我们不妨给出dist[i] = i。 然后每一个节点的w就是它的dist-父节点的dist。
千万不要忘了,你是求w[i],不是dist[i]
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i) for (int i = 1; i <= n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
int p[N],fa[N],ans[N];
void solve()
{int n;cin>>n;for(int i=1;i<=n;i++) cin>>fa[i];for(int i=1;i<=n;i++) cin>>p[i],ans[i]=0;if(p[1]!=fa[p[1]]){//如果最小的不是父节点cout<<-1<<endl;return;}ans[p[1]]=1;for(int i=2;i<=n;i++){if(!ans[fa[p[i]]]){//如果它的父节点还没有遍历到,说明顺序不对了cout<<-1<<endl;return;}ans[p[i]]=i;}for(int i=1;i<=n;i++){cout<<ans[i]-ans[fa[i]]<<" ";输出w[i];}cout<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
E1. Escape The Maze (easy version)
题目大意:朋友和你同时走,是否在朋友之前走到出口,即叶节点。
思路:bfs多源问题,因为是同时动,所以可以用bfs找出口,如果有一条路可以在朋友之前走完,就是可行的。注意:处理上要先存朋友的位置,因为朋友和你同时到达的位置也不可以走。
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i) for (int i = 1; i <= n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
vector<int> cun[N];//地图
queue<PII> q;
int n,k;
int vis[N]; //判断是否走过
int a[N];//存它的朋友
bool bfs()
{memset(vis, 0, sizeof vis);for (int i = 0; i < k; i++){q.push({a[i], 0});vis[a[i]] = 1;} //0表示是朋友;vis[1] = 1;q.push({1, 1});while (q.size()){PII tmp = q.front();q.pop();int now = tmp.ff;if (now != 1 && cun[now].size() == 1 && tmp.ss == 1)return 1; //找到出口for (auto i : cun[now]){if (vis[i])continue;vis[i] = 1;q.push({i, tmp.ss});}}return 0;
}
void solve()
{int x, y;cin >> n >> k;for (int i = 0; i < k; i++)cin >> a[i];for (int i=1;i<=n;i++) cun[i].clear();for (int i = 1; i < n; i++){cin >> x >> y;cun[x].push_back(y);cun[y].push_back(x);}while (q.size())q.pop();cout << (bfs() ? "YES" : "NO") << endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
E2. Escape The Maze (hard version)
题意:就是朋友太多了,他们想用最少的朋友堵住他。如果本身就堵不住,那就输出-1;
思路:和上一题一样,多加一个他走不过去的地方都是什么朋友卡住。然后输出卡住他的朋友的数量
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i) for (int i = 1; i <= n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
vector<int> cun[N];//地图
queue<PII> q;
int n,k;
int from[N];//存他从哪个点来
int vis[N]; //判断是否走过
int a[N];//存它的朋友
set<int>st;//存储他碰到哪些朋友走过的路
int bfs()
{st.clear();memset(vis, 0, sizeof vis);for (int i = 0; i < k; i++){q.push({a[i], 0});from[a[i]] = a[i];vis[a[i]] = 1;} //0表示是朋友;vis[1] = 1;q.push({1, 1});from[1] = 1;//從本身來while (q.size()){PII tmp = q.front();q.pop();int now = tmp.ff;//現在在哪個點if (now != 1 && cun[now].size() == 1 && tmp.ss == 1)return -1; //找到出口無法堵住他for (auto i : cun[now]){if (vis[i]){if(from[now] == 1 && from[i] != 1) st.insert(from[i]); //从根节点来到一个朋友已到过的节点continue;}from[i] = from[now];vis[i] = 1;q.push({i, tmp.ss});}}return st.size();
}
void solve()
{int x, y;cin >> n >> k;for (int i = 0; i < k; i++)cin >> a[i];for (int i=1;i<=n;i++) cun[i].clear();for (int i = 1; i < n; i++){cin >> x >> y;cun[x].push_back(y);cun[y].push_back(x);}while (q.size())q.pop();cout<<bfs()<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}
F. ATM and Students
题意:找一段学生取钱或者存钱;
思路:双指针,固定左边取右边。右边一定大于等于上一次的右边。
证明:如果a[l]是正数,那么去除后,上次的右边结束的值一定小于大于这次,上次小于0,所以这次也小于0,如果是负数,那么过程中肯定始终大于上次过程。
#include <bits/stdc++.h>
#define int long long
#define PII pair<int, int>
#define endl "\n"
#define fast ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fer(i) for (int i = 1; i <= n; i++)
#define ff first
#define ss second
using namespace std;
const int N = 3e5 + 11;
int a[N];
void solve()
{int n, s;cin >> n >> s;int tt = 0; //开始for (int i = 0; i < n; i++){cin >> a[i];}int ansr, ansl, maxn = 0;while (a[tt] + s < 0)//找到从什么时候开始++tt;int sum = a[tt];for (int l = tt, r = tt; l < n; l++){while (r + 1 < n && s + sum + a[r + 1] >= 0)sum += a[++r];if (s + sum >= 0 && maxn < r - l + 1){maxn = r - l + 1;ansr = r;ansl = l;}sum-=a[l];}if (maxn<=0) cout<<"-1"<<endl;else cout<<ansl+1<<" "<<ansr+1<<endl;
}
signed main()
{fast;int t;cin >> t;while (t--)solve();
}