目前:

1,2,3,edu134,818,819

1.不做几何和2600以上的题:

Dashboard - Codeforces Beta Round #1 - Codeforces

1A:这道题我们就贪心就完了:我们尽可能将超出范围的aXa数量变小:可以画个图来理解理解

#include<iostream>
using namespace std;
long long n, m, a;
int main()
{long long ans1, ans2;cin >> n >> m >> a;cout<<(n+a-1)/a*(m+a-1)/a;
}

1B:这道题认真看的话其实就是一个26进制而已:

写法上有些不同 要注意的点在于此时的假如一个数%26=0 代表此时最后位为z 该数/=26后还要-1

/*
1.26 进制
*/
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
#define int long long
const int maxn = 3e5 + 10;
string s;
void solve()
{cin >> s;int ok = 0;int len = s.length();int op = 0;//用来判断哪种形式的if (s[0] == 'R'){for (int i = 1; i < len; i++){if ('0' <= s[i] && s[i] <= '9'){continue;}else{if (s[i] == 'C'){ok = i;break;}else{ok = 0;break;}}}if (ok != 1 && ok != 0){op = 1;}else{op = 2;}}elseop = 2;if (op == 1){int ok1 = 0;for (int i =ok+1; i <len; i++){ok1 = 10 * ok1 + (s[i] - '0');}string s1;int len1 = 0;while (ok1){len1++;int now = ok1 %26;char s2 = ('A' +now-1);ok1 /= 26;if (now == 0)ok1--;if (s2 == 'A' - 1)s2 = 'Z';s1.push_back(s2);}for (int i = len1 - 1; i >=0; i--)cout << s1[i];for (int i = 1; i < ok; i++)cout << s[i];cout << endl;}else{int ok1 = 0;int op1;for (int i = 0; i < len; i++){if (s[i] >= '0'&&s[i] <= '9'){   op1 = i;break;}else{ok1 = 26 * ok1 + s[i] - 'A' + 1;}}cout << "R";for (int i = op1; i < len; i++)cout << s[i];cout << "C";cout << ok1 << endl;}
}
signed main()
{int t;cin >> t;while (t--)solve();
}

Dashboard - Codeforces Beta Round #2 - Codeforces

2A:

这道题的注意点在于我们要维护的是所有处理完的数 而不是中途的最大值:

写法在于我们此时先记录一下过程 并维护每个人的最后结果数字 然后我们找到此时的最大值

之后再按这个方式来维护一下过程 假如找到此时和大于最大值的第一个人 就将其输出:

本质为模拟题:

#include<bits/stdc++.h>
using namespace std;
#define int long long
map<string, int> mp, mpp;
int n, a[100001], maxn =0;
string s[100001], s1;
signed main()
{cin >> n;for (int i = 1; i <= n; i++){cin >> s[i] >> a[i];mp[s[i]] += a[i];//记录数值}for (int i = 1; i <= n; i++){maxn = max(maxn, mp[s[i]]);//取最大}for (int i = 1; i <= n; i++)//谁先到达maxn的就取谁{mpp[s[i]] += a[i];if (mp[s[i]] == maxn && mpp[s[i]] >= maxn){s1 = s[i];break;}}cout << s1;return 0;
}

2B:

这道题的最重要的一个点在于我10=2*5 即 10 只能是由2*5变来的 所以一条路上最小的0个数是由该路上min(num(2),num(5))来决定的 而这个求最小的一般是利用dp来转移的

同时要注意的一点在于假如我们存在0这个数 那么可以发现此时 我们只要ans>1 我们都可以强制让其经过0 使其ans=1

关于输出的话 就bfs就好了

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
const int maxn = 1e3 + 10;
int dp1[maxn][maxn];
int dp2[maxn][maxn];
int a[maxn][maxn];
int b[maxn][maxn], c[maxn][maxn];
void dfs(int x, int y, int k)//k代表此时我要以
{//cout << x << ' ' << y << endl;if (k == 2){if (x == 1 && y == 1)return;if (x != 1 && dp1[x - 1][y] + b[x][y] == dp1[x][y]){dfs(x - 1, y, k);cout << 'D';}else if(y!=1&&dp1[x][y-1]+b[x][y]==dp1[x][y]){dfs(x, y - 1,k);cout << "R";}}else{if (x == 1 && y == 1)return;if (x != 1 && dp2[x - 1][y] + c[x][y] == dp2[x][y]){dfs(x - 1, y, k);cout << 'D';}else if (y != 1 && dp2[x][y - 1] + c[x][y] == dp2[x][y]){dfs(x, y - 1, k);cout << "R";}}
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int n;cin >> n;int ok = 0;  int idx, idy;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){cin >> a[i][j];int m = a[i][j];if (a[i][j] == 0){ok = 1; idx = j, idy = j;}while (a[i][j]%2==0&&a[i][j]!=0){b[i][j]++;a[i][j] /= 2;}while (m%5==0&&m!=0){c[i][j]++;m /= 5;}}}memset(dp1, 0x3f, sizeof dp1);memset(dp2, 0x3f, sizeof dp2);dp1[1][1] = 0;dp2[1][1] = 0;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (i != 1) {dp1[i][j] = dp1[i - 1][j];dp2[i][j] = dp2[i - 1][j];}if (j != 1){dp1[i][j] = min(dp1[i][j], dp1[i][j - 1]);dp2[i][j] = min(dp2[i][j], dp2[i][j - 1] );}dp1[i][j] += b[i][j];dp2[i][j] += c[i][j];}}int ans = min(dp1[n][n], dp2[n][n]);if (ans > 1 && ok){cout << 1 << endl;for (int i = 1; i < idx; i++){cout << "R";}for (int i = 1; i < n; i++)cout << "D";for (int i = idx; i < n; i++)cout << "R";return 0;}cout << ans<< endl;if (ans == dp1[n][n])//代表此时是以2为标准{dfs(n, n, 2);}else{dfs(n, n, 5);}
}

2C几何

Dashboard - Codeforces Beta Round #3 - Codeforces

3A:

这道题的关键在于组合 :
我们举个例子来说明:假如此时从起点到终点要 向右5 向上6 我们可以将向上和向右维护到一起 这样的话我们此时 右上=min(右,上) 然后还有一步向上是无法被抵消的 所以此时最短要6步

类似这样的思路 我们模拟就好了:

#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
#define int long long
string s1, s2;
signed main()
{cin >> s1 >> s2;int beginx = s1[1] - '0';int beginy = s1[0] - 'a' + 1;int endx = s2[1] - '0';int endy = s2[0] - 'a' + 1;if (beginx < endx){if (beginy < endy){int minnr = abs(endy - beginy);int minnu = abs(endx - beginx);int ans = max(minnr, minnu);cout << ans << endl;for (int i = 1; i <=min(minnr, minnu);i++){cout << "RU" << endl;}for (int i = min(minnr, minnu) + 1; i <= ans; i++){if (minnr > minnu){cout << "R" << endl;}elsecout << "U" << endl;}}else if(beginy>=endy){int minnl = abs(endy - beginy);int minnu = abs(endx - beginx);int ans = max(minnl, minnu);cout << ans << endl;for (int i = 1; i <= min(minnl, minnu); i++){cout << "LU" << endl;}for (int i = min(minnl, minnu) + 1; i <= ans; i++){if (minnl > minnu){cout << "L" << endl;}elsecout << "U" << endl;}}}else{if (beginy < endy){int minnr = abs(endy - beginy);int minnu = abs(endx - beginx);int ans = max(minnr, minnu);cout << ans << endl;for (int i = 1; i <= min(minnr, minnu); i++){cout << "RD" << endl;}for (int i = min(minnr, minnu) + 1; i <= ans; i++){if (minnr > minnu){cout << "R" << endl;}elsecout << "D" << endl;}}else if (beginy >= endy){int minnl = abs(endy - beginy);int minnu = abs(endx - beginx);int ans = max(minnl, minnu);cout << ans << endl;for (int i = 1; i <= min(minnl, minnu); i++){cout << "LD" << endl;}for (int i = min(minnl, minnu) + 1; i <= ans; i++){if (minnl > minnu){cout << "L" << endl;}elsecout << "D" << endl;}}}
}

3B:对于这道题 本来我是想直接贪心的 就类似于01背包问题时 我们都学过的错误写法 可是由于这玩意基本来说就是错误的所以没有写:

正解: 我们可以发现此时的体积就两种情况 这样划分一定有什么用处 由于我们此时最后的体积划分一定是 1 1 1  1 2 1 1 这类写法 所以我们可以枚举我们此时选择多少个1 然后表示(因为此时我们将背包尽可能填满)此时我们选择多少个2就可以直接算出来了 根据贪心来想的话此时我们可以发现 我们从大到小排 维护一个sum 接下来就好写了:

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 2e5 + 10;
int sum1[maxn], sum2[maxn];
struct node
{int id, x;inline bool operator<(const node&m)const{return x > m.x;}
}po1[maxn], po2[maxn];
int ans = 0;
signed main()
{int n, k;cin >> n >> k;int cnt1 = 0, cnt2 = 0;for (int i = 1; i <= n; i++){int o, l;cin >> o >> l;if (o == 1){po1[++cnt1].id = i, po1[cnt1].x = l;}else{po2[++cnt2].id = i, po2[cnt2].x = l;}}sort(po1 + 1, po1 + 1 + cnt1);sort(po2 + 1, po2 + 1 + cnt2);for (int i = 1; i <= cnt1; i++){sum1[i] = sum1[i - 1] + po1[i].x;}for (int i = 1; i <= cnt2; i++){sum2[i] = sum2[i - 1] + po2[i].x;}int id1=0, id2=0;for (int i = 0; i <= cnt1; i++){int nowans = sum1[i];int now = k - i;if (now < 0)break;int idx;if (now/2<=cnt2){       nowans += sum2[now/2];idx = now / 2; }else{nowans += sum2[cnt2];idx = cnt2;}if (nowans>ans){ans = nowans;id1 = i;id2 = idx;}}cout << ans << endl;for (int i = 1; i <= id1; i++){cout << po1[i].id << ' ';}for (int i = 1; i <= id2; i++){cout << po2[i].id << ' ';}
}

3C:这道题说了一大堆就是一个判断题而已 我们几个if就可以搞定了‘

#include<iostream>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
int main() {map<char, int> qipan;string chess[3];int sflag = 0, fflag = 0;for (int i = 0; i < 3; i++) {cin >> chess[i];//first 玩家为X     second 玩家为0     空地为 . qipan[chess[i][0]]++;qipan[chess[i][1]]++;qipan[chess[i][2]]++;}if (qipan['X'] < qipan['0'] || qipan['0'] < qipan['X'] - 1) {cout << "illegal";return 0;}if (chess[0][0] == chess[0][1] && chess[0][1] == chess[0][2] && chess[0][0] != '.') {if (chess[0][0] == '0') sflag = 1;if (chess[0][0] == 'X') fflag = 1;}if (chess[1][0] == chess[1][1] && chess[1][1] == chess[1][2] && chess[1][0] != '.') {if (chess[1][0] == '0') sflag = 1;if (chess[1][0] == 'X') fflag = 1;}if (chess[2][0] == chess[2][1] && chess[2][1] == chess[2][2] && chess[2][0] != '.') {if (chess[2][0] == '0') sflag = 1;if (chess[2][0] == 'X') fflag = 1;}if (chess[0][0] == chess[1][0] && chess[1][0] == chess[2][0] && chess[0][0] != '.') {if (chess[0][0] == '0') sflag = 1;if (chess[0][0] == 'X') fflag = 1;}if (chess[0][1] == chess[1][1] && chess[1][1] == chess[2][1] && chess[0][1] != '.') {if (chess[0][1] == '0') sflag = 1;if (chess[0][1] == 'X') fflag = 1;}if (chess[0][2] == chess[1][2] && chess[1][2] == chess[2][2] && chess[0][2] != '.') {if (chess[0][2] == '0') sflag = 1;if (chess[0][2] == 'X') fflag = 1;}if (chess[0][0] == chess[1][1] && chess[1][1] == chess[2][2] && chess[0][0] != '.') {if (chess[0][0] == '0') sflag = 1;if (chess[0][0] == 'X') fflag = 1;}if (chess[0][2] == chess[1][1] && chess[1][1] == chess[2][0] && chess[0][2] != '.') {if (chess[0][2] == '0') sflag = 1;if (chess[0][2] == 'X') fflag = 1;}if (sflag == 1 && fflag == 1 || (sflag == 1 && qipan['X'] > qipan['0']) || (fflag == 1 && qipan['X'] == qipan['0'])) {cout << "illegal";return 0;}if (sflag == 1) {cout << "the second player won";return 0;}if (fflag == 1) {cout << "the first player won";return 0;}if (qipan['X'] == qipan['0'] && qipan['.'] != 0) {cout << "first";return 0;}if (qipan['X'] > qipan['0'] && qipan['.'] != 0) {cout << "second";return 0;}cout << "draw";return 0;
}

3D:这道题我本来是想利用dp[i][j]代表前i个数中sum为j的最小代价来维护的 可是这样写的话0(n^2) 不太可能 我看了答案 他的话就是贪心的写法 :

首先对于这种?填左或则右的类型 我们比较常见的写法都是先全填)然后再进行维护 后面有一次比赛好像也考了类似的问题:

所以我们假设此时全部填)然后对一个位置进行考虑 :假如此时位置(<)代表 此时(少了 我们必须将前面的一个)-》( 所以此时我们维护一个优先队列维护我们此时变化的值 取其中最大的

然后就是判断是否合法了;

最后注意特判一下)???( 这类情况就好了:

#include<queue>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 1e5 + 10;
struct node
{int data;int id;bool operator<(const node&m)const{return data > m.data;}
}t;
priority_queue<node>q;
string s;
signed main()
{int cnt = 0;int ans = 0;int a, b;cin >> s;for (int i = 0; i < s.length(); i++){if (s[i] == '(')cnt++;else{cnt--;if (s[i] == '?'){cin >> a >> b;t.data = a - b;t.id = i;q.push(t);s[i] = ')';ans += b;}}while(cnt < 0){if (q.empty()){ans = -1;break;}if (ans != -1){cnt += 2;t = q.top();q.pop();s[t.id] = '(';ans += t.data;}}}if (s[0] == ')' || s[s.length() - 1] == '(')ans = -1;if (cnt){ans = -1;}cout << ans << endl;if (ans != -1){cout << s;}
}





Dashboard - Educational Codeforces Round 134 (Rated for Div. 2) - Codeforces

A:





Dashboard - Codeforces Round #818 (Div. 2) - Codeforces

A:题中lcm/gcd=a*b/(gcd(a,b))^2 可以转化为 此时两个互质的数相乘 <=3 所以此时 1*1,2*1,1*2,3*1,1*3

所以答案为:n+2*(n/2+n/3)

B:此时我们可以发现假如没有r,c的话 我们只要 i%k==j%k 就好了 就是k的循环 当此时存在r,c的话 我们考虑将这一行给提前维护后输出 或者 利用 ((i-r)%k+k)%k==((j-c)%k+k)%k

以(r,c)为中心扩展对角线就好了

C:此时我们可以发现a数组可以无限变大 但最后维护的数组有一个前提:a[i]<a[i+1]+1(或者没有变和之前的一样)

假如b数组中存在b[i]>b[i+1]+1 此时必须要求 b[i]==a[i]即本来就是这个类型

还要考虑之前是否存在a[i]<b[i]的情况

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 2e5 + 10;
int n, k;
int a[maxn], b[maxn];
void solve()
{cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];for (int i = 1; i <= n; i++)cin >> b[i];b[0] = b[n]; a[0] = a[n];for (int i = 1; i <= n; i++){if (a[i%n] > b[i%n] || (a[i%n] != b[i%n] && b[i%n] > b[i%n + 1] + 1)){cout << "NO"<<endl;return;}}cout << "YES" << endl;return;
}
signed main()
{int t;cin >> t;while (t--)solve();
}

D:本来看成最小号为多少号 结果不是:

我们考虑最后均为左边获胜 假如我们转移一次 此时到根节点失败次数为1 的话可以胜利 同理 转移k次  到达根节点失败次数为k的人可以胜利 因为每个人到根节点均有n次 其中k次为负的人数为C(n,k) 所以我们利用组合数求和一下  说人话就是 n次比赛中选择k次失败的种类

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
int fact[maxn], invfact[maxn];
int qpow(int a, int b)
{int res = 1;while (b){if (b & 1){res = res * a%mod;}b >>= 1;a = a * a%mod;}return res;
}
void init() {fact[0] = invfact[0] = 1;for (int i = 1; i < maxn; i++)fact[i] = fact[i - 1] * i%mod;invfact[maxn - 1] = qpow(fact[maxn - 1], mod - 2);for (int i = maxn - 2; i; i--)invfact[i] = invfact[i + 1] * (i + 1) % mod;
}
int q_mul(int a, int b) {a %= mod; b %= mod;int ans = 0;while (b) {if (b & 1)ans = (ans + a) % mod;a = (a + a) % mod;b >>= 1;}return ans % mod;
}
int C(int a, int b) {if (a < b)return 0;return q_mul(fact[a], q_mul(invfact[b], invfact[a - b])) % mod;
}
signed main()
{init();int n, k;cin >> n >> k;int ans = 0;for (int i = 0; i <= min(k, n); i++){ans += C(n, i);ans %= mod;}cout << ans;
}

E:对于这道题 复杂度已经被确定为nlogn 或者nsqrt(n)  所以我们尝试枚举c

a+b的值就是n-c 由于a,b为gcd(a,b)的倍数 此时a+b 一定为gcd(a,b)的倍数 此时我们枚举(a+b)的因子就可以找到所有的对 :c,gcd(a,b) 但此时还要考虑每一对有多少个  因为此时 a/d 和 (a+b)/d 互质 我们考虑a/d 的个数就是考虑小于(a+b)/d 且和 其互质的数的个数 :为欧拉函数

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int maxn=1e5+10;//代表前n个数中于n互质的数的个数   方法:ola筛素数
int m[maxn], phi[maxn], p[maxn];//m[i]表示i是不是素数,p为存放素数的数组,phi为欧拉函数
void ola(int x){//1-x中每一位ola函数phi[1] = 1;for (int i = 2; i <= x; i++){if (!m[i]){p[++p[0]] = i;phi[i] = i - 1;}for (int j = 1; j <= p[0] && i*p[j] <= x; j++){m[p[j] * i] = 1;//利用最小的因数来筛掉该数:p[j]为最小质因子,i为放大倍数if (i%p[j] == 0){//看p[j]是否为i的约数,要是i%p[j]==0代表它两不互质phi[p[j] * i] = phi[i] * p[j];break;
//break的含义为当i=k*p[j]时,要是我们继续循环下去m【i*p【j+1】】=1
//i*p[j+1]=k*p[j]*p[j+1]这个数,会在i=k*p【j+1】时再次被消掉,重复
//同时由于我们是要利用最小的质因子来消掉的所以我们要在当i=k*p[j+1]是消掉他(因为i为放大倍数)}else{phi[p[j] * i] = phi[i] * (p[j] - 1);//p[j]-1就是phi[p[j]],}}
}
}
signed main()
{int n;cin>>n;ola(n);int ans=0;for(int c=1;c<=n-2;c++){int t=n-c;for(int d=1;d*d<=t;d++)//枚举a+b的因数 以为此时假如d为a和b共有的因数那么也是a+b的因数 {//此时我们枚举了 c和gcd(a,b) 现在考虑gcd(a,b)的个数: 由于此时a/d和b/d互质 此时我们发现:a/d 和t/d也是互质 此时我们可以发现 a/d <t/d 一定存在所以此时a/d 的个数就是 phi[t/d]if(t%d==0){ans+=(c*d/__gcd(c,d))*phi[t/d]%mod;if(d!=1&&d*d!=t)ans+=(c*t/d/__gcd(c,t/d))*phi[d]%mod;}ans%=mod;}}cout<<ans%mod;
}



Dashboard - Codeforces Round #819 (Div. 1 + Div. 2) and Grimoire of Code Annual Contest 2022 - Codeforces

A:A的话我们可以发现此时翻转可以不限次数,由于我们答案仅由1,n位置决定此时我们考虑3种情况:

1.保留1号位 挑后面最大的安排到n号位

2.保留n号位挑最小的安排到1号位

3.我们此时全部翻转 可以发现此时答案为 相邻两个差的最大值:(前-后)

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
using namespace std;
#define int long long
#define endl '\n'
const int maxn = 2e5 + 10;
int a[maxn], n, m;
void solve()
{cin >> n;int maxx = 0, minn = 1e9;int ans = -1e9;for (int i = 1; i <= n; i++){     cin >> a[i];}for (int i = 1; i <= n; i++){if (i != 1) {maxx = max(maxx, a[i]);}if (i != n)minn = min(minn, a[i]);if (i != n)ans = max(a[i] - a[i + 1], ans);}if (n == 1){cout << 0 << endl;return;}ans = max({ ans,maxx-a[1], a[n] - minn });cout << ans << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int t;cin >> t;while (t--)solve();
}

B:对于这道题 我们可以发现我们的最优写法就是维护每个数都有偶数位 除了最大的数可以不用

按这个思路来想 我们假如此时有奇数个位置 可以将前n-1 安排为1 剩下的安排到n位

假如此时有偶数位 我们至少要留出2个位给其他的来分配 其余变为1 因为我们假如将其他位也变大的话 此时是要从剩下的数中掏出来2 所以假如此时剩下的数不为偶数我们就无法分配

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
using namespace std;
#define int long long
#define endl '\n'
const int maxn = 2e5 + 10;
int a[maxn], n, m;
void solve()
{cin >> n>>m;if (m < n){cout << "NO" << endl;}else{if (n % 2 == 1){cout << "YES" << endl;for (int i = 1; i <= n; i++){if (i != n){cout << 1 << ' ';}elsecout << (m - (n - 1)) << ' ';}cout << endl;}else{int cnt = 0;if ((m - (n - 2)) % 2 == 0) {cout << "YES" << endl;for (int i = 1; i <= n; i++){if (i <= n - 2){cout << 1 << ' ';}else{cout << (m - (n - 2)) / 2 << ' ';}}cout << endl;}else{cout << "NO" << endl;}}}
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int t;cin >> t;while (t--)solve();
}

C:我们可以发现 对于类似((()))的情况 中间的(())无法和其他的联系 只能作为两独立的东西来看待 但最外围的却可以和其他最外围的相连 所以此时我们只要维护一个每个的深度-1 加起来再+1 就是答案了

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
#include<queue>
#include<string>
#include<stack>
#include<map>
using namespace std;
#define int long long
#define endl '\n'
const int maxn = 2e5 + 10;
string s;
int a[maxn], n, m;
int fa[maxn];
int find(int x)
{if (x == fa[x])return x;elsereturn fa[x] = find(fa[x]);
}
struct node
{int id, val;
};
queue<node>st;
void solve()
{int len;cin >> len;cin >> s;int cnt = 0;int ans = 0;for (int i = 2 * len - 1; i >= 0; i--){if (s[i] == ')'){int now = 1;while (s[i - now] != '('){now++;}ans += now;i = i - now;ans -= 1;cnt++;}}cout << ans + 1 << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int t;cin >> t;while (t--)solve();
}

D:

考虑此时我们要将哪条变进行变化: 可以发现此时我们将任意一条边变化对蓝色方的减小均为1

假如此时变化的边和蓝色围成环的话此时答案不会减小

但对于红色方却有讲究假如我们将一个环的一条边划掉的话此时答案不会变大 但假如这条边不少的话此时我们会将区域划分为2分 答案就会+1

所以此时我们要两边均不是环的情况

考虑此时我们利用n-1 将这个图维持一个树 考虑剩下最多3条边是否可能维护围一个环假如会的话我们此时再更新就好了

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
#include<queue>
#include<string>
#include<stack>
#include<map>
using namespace std;
#define int long long
#define endl '\n'
const int maxn = 2e5 + 10;
string s;
int a[maxn], n, m;
int fa[maxn],fa1[maxn];
int find(int x)
{if (x == fa[x])return x;elsereturn fa[x] = find(fa[x]);
}
int find1(int x)
{if (x == fa1[x])return x;elsereturn fa1[x] = find1(fa1[x]);
}
struct node
{int l, r;
}e[maxn];
bool vis[maxn];
void solve()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; i++)vis[i] = 0;for (int i = 1; i <= n; i++)fa[i] = i;for (int i = 1; i <= m; i++){cin >> e[i].l >> e[i].r;}for (int i = 1; i <= m; i++){int fx = find(e[i].l), fy = find(e[i].r);if (fx != fy){fa[fx] = fy;}else{vis[i] = 1;}}for (int i = 1; i <= n; i++)fa1[i] = i;for (int i = 1; i <= m; i++){if (vis[i]){int fx = find1(e[i].l), fy = find1(e[i].r);if (fx != fy){fa1[fx] = fy;}else{for (int j = 1; j <= n; j++)fa[j] = j;fx = find(e[i].l), fy = find(e[i].r);fa[fx] = fy;for (int j = 1; j <= m; j++){if (vis[j] == 0) {fx = find(e[j].l), fy = find(e[j].r);if (fx != fy){fa[fx] = fy;}else{vis[j] = 1;break;}}}vis[i] = 0;break;}}}for (int i = 1; i <= m; i++)cout << vis[i];cout << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);int t;cin >> t;while (t--)solve();
}

E及后面的题之后更新

codeforces:从第1场开始的刷题记录:记录每场参加的cf相关推荐

  1. Educational Codeforces Round 131 (Rated for Div. 2)刷题记录OR题解

    题解 A Grass Field 题面翻译 给出一个 2×22 \times 22×2 的矩阵,矩阵的值都是 000 和 111,定义一次操作:选择一个点,将其所在的行和列的点的值全部修改为 000, ...

  2. bzoj刷题(shui)记录

    放假刷了一个月的水题,集中写一下题解吧. bzoj1858:线段树随便维护一下. code bzoj2705:莫比乌斯反演裸题. code bzoj1202:并查集,但是我写了一种跟floyd很像的奇 ...

  3. 刷题练习记录(3)——无重复字符的最长子串(JAVA 和 Python)——set()函数/集合...

    [题号003]无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的 ...

  4. HDLBits刷题全记录(五)

    文章目录 Finite State Machines Simple FSM 1_1(asynchronous reset) Simple FSM 1_2(synchronous reset) Simp ...

  5. [buuctf]crypto刷题学习记录(1-22)

    目录 一.MD5 二.Url编码 三.看我回旋踢 四.一眼就解密 五.摩丝 六.[BJDCTF 2nd]签到-y1ng 七.[BJDCTF 2nd]password 八.变异凯撒 九.Quoted-p ...

  6. LeetCode 刷题思路记录

    数组篇 题1 两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一 ...

  7. c语言贪心算法合并箭,LeetCode刷题题库:贪心算法

    LeetCode刷题笔记:贪心算法 自大学开始,我便陆陆续续的学习一些 算法和数据结构 方面的内容,同时也开始在一些平台刷题,也会参加一些大大小小的算法竞赛.但是平时刷题缺少目的性.系统性,最终导致算 ...

  8. 面试 | 推荐几个程序员刷题的网站!面试必备!!!

    经常有朋友问我,有没有在线刷题的网站推荐. 为什么要用线上刷题呢?确实有一定好处,线上的笔试题有自动更新,可以记录你刷题的记录,更好的来统计你的错误率和错误题型. 最主要的是方便,不用自己再去找各个类 ...

  9. 【牛客刷题】游戏行业通识(更新中)

    刷题日期记录 [2023.2.9]搜狐畅游2019校招笔试题-技术美术 1 金庸小说 下面()不是金庸撰写的小说?_搜狐畅游笔试题_牛客网 (nowcoder.com) 居然问这个kkk不愧是游戏题, ...

最新文章

  1. 论坛报名 | AI赋能未来交通
  2. Hibernate智能化分页
  3. php 查询datetime,急急PHP,数据库中createtime字段类型为datetime,怎样根据这个查询一段时间内的数据...
  4. android view强制重绘_android view 相关方法 layout draw 布局 重绘 | 学步园
  5. LINUX下用脚本实现JDK+TOMCAT
  6. 树——一种数据结构(二)
  7. [EMNLP2017]Global Normalization of Convolutional Neural Networks for Joint Entity and Relation(阅读笔记)
  8. html常用语言代码大全,常用的html代码大全
  9. 北理复试上机题2010年
  10. Matrix Operations -- Transpose +Determinant + Adjugate+ Inverse + Gram-Schimidt +LUP + QR + Eigen
  11. 兔子数列规律怎么讲_兔子数列规律
  12. 玩转直播:如何从 0 到 1 构建简单直播系统
  13. C++实现坦克大战(超详细)(文末附源码!!!)
  14. 垃圾收集概述和垃圾收集算法(超详细介绍)
  15. DeepTraLog: Trace-Log Combined Microservice AnomalyDetection through Graph-based Deep Learning
  16. Linux使用vi修改、删除、保存文件
  17. 桌面显卡天梯图2023年2月 台式机显卡天梯图2023
  18. html 按钮立体效果,纯CSS实现的立体按钮
  19. 谷歌创始人退位!印度籍 CEO 这是要“接管”美国科技圈?
  20. matplotlib 第二章学习

热门文章

  1. 对Linux既拉又打 微软与开源的“爱恨情仇”
  2. 处理器经历了6大发展阶段!什么是协处理器?
  3. 【python】设计一个游戏角色类 属性:角色名、血量、魔法、状态 方法:释放技能 被伤害 要求:设计要合理
  4. 服饰商标的分类是什么?
  5. 谷歌AI要为你写诗!让诗意文字浮现在你自拍头像上
  6. WindowsServer操作系统安全
  7. 计算机毕业设计ssm基于java的仓储信息管理系统o9ypl系统+程序+源码+lw+远程部署
  8. 程序员数学(3)--一元一次方程
  9. 用Java做爬虫爬取王者荣耀的英雄头像
  10. 安卓模拟器排行_安卓手机修改王者荣耀战区教程来了!!!