Codeforces Round 665 (div2)
2020.8.22
裝修完了我的部落格,喜歡這個造型,掛上友鏈就更好了
昨天cf就是一個徹頭徹尾的悲劇,本來能上藍,結果因為在A題耽誤時間過多導致掉了30分,不過沒關係,這算是一個小波動吧,影響不了什麼,現在穩定到每場3題打底了,下場打回來就行了。、
A題.Distance and Axis
這道題我剛跟朋友聊完天,乍一看有些懵,想了半個小時最後才出來。謝謝木下巨佬給的tips,就是首先觀察到當OB 變動1,那麼差距變動2,所以我們一定是需要一個偶數的差距才能不移動,如果n比m大,那麼挪過去就行了,其實很簡單,但是當時怎麼也想象不出這個動作
#include <bits/stdc++.h> usingAC Codenamespace std; #define limit (10000000 + 5)//防止溢位 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步兩步 #define EPS 1e-6 #define FASTIO ios::sync_with_stdio(false);cin.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a,b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #defineper(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout) #definedebug(x) cout<<x<<endl typedef long long ll; typedef unsigned long long ull; inline ll read(){ ll sign = 1, x = 0;char s = getchar(); while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();} while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();} return x * sign; }//快讀 void write(ll x){ if(x < 0) putchar('-'),x = -x; if(x / 10) write(x / 10); putchar(x % 10 + '0'); } int n,kase,m; int a[limit]; int main() { #ifdef LOCAL FOPEN; #endif cin>>kase; while (kase--){ cin>>n>>m; if(n < m){ cout<<abs(n - m)<<endl; }else if((n - m) & 1){ cout<<1<<endl; }else{ cout<<0<<endl; } } return 0; }
B題.Ternary Sequence
這道題就是問怎麼安排序列使得序列和最大,給出來了規則,那麼就看啊,首先肯定是2越多越好,而且只有2,因為無論是1還是0乘積都只可能有0,好的。然後用剩下的1互相抵消,因為避免對方的2和己方1結合扣分,然後用1減0,最後安排不了的才和2結合從答案中減去,就不用管了,反正其餘對答案的貢獻鐵定為0,這個邏輯好繞啊,我昨天不知道是怎麼硬著頭皮寫出來的,程式碼太醜陋了,但還是過了。聽說有人寫完79行if else直接關電腦的,艹。
#include <bits/stdc++.h> using namespace std; #define limit (10000000 + 5)//防止溢位 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步兩步 #define EPS 1e-6 #define FASTIO ios::sync_with_stdio(false);cin.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a,b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout) #define debug(x) cout<<x<<endl typedef long long ll; typedef unsigned long long ull; inline ll read(){ ll sign = 1, x = 0;char s = getchar(); while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();} while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();} return x * sign; }//快讀 void write(ll x){ if(x < 0) putchar('-'),x = -x; if(x / 10) write(x / 10); putchar(x % 10 + '0'); } int n,kase,m; int a[limit]; int main() { #ifdef LOCAL FOPEN; #endif cin>>kase; while (kase--){ cin>>n>>m; if(n < m){ cout<<abs(n - m)<<endl; }else if((n - m) & 1){ cout<<1<<endl; }else{ cout<<0<<endl; } } return 0; }AC Code
C題Mere Array
這題問的是如果序列裡任意兩個元素的gcd等於最小值就能交換,問能不能變成非嚴格上升序列。首先說升序,那麼就想到sort一遍拷貝之後的陣列,然後比較,那麼一個元素能換到其本身應該所處位置的充要條件是這個數字能夠整除最小值,所以做法如下,往常的話我今天已經鐵藍了,但A耽誤時間太長了,還wa了兩次,到C的排名才3k9,今天必須做到d才能不掉分
#include <bits/stdc++.h> using namespace std; #define limit (10000000 + 5)//防止溢位 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步兩步 #define EPS 1e-6 #define FASTIO ios::sync_with_stdio(false);cin.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a,b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout) #define debug(x) cout<<x<<endl typedef long long ll; typedef unsigned long long ull; inline ll read(){ ll sign = 1, x = 0;char s = getchar(); while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();} while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();} return x * sign; }//快讀 void write(ll x){ if(x < 0) putchar('-'),x = -x; if(x / 10) write(x / 10); putchar(x % 10 + '0'); } int n,kase,m; int a[limit]; int f[limit]; int main() { #ifdef LOCAL FOPEN; #endif cin>>kase; while (kase--){ cin>>n; int minn = INF; int flag = 1; rep(i,1,n){ cin>>a[i]; minn = min(minn, a[i]); f[i] = a[i]; } sort(f + 1, f + 1 + n); flag = 0; rep(i ,1,n){ if(a[i] != f[i] && a[i] % minn != 0){ flag = 1; cout<<"NO"<<endl; break; } } if(!flag){ cout<<"YES"<<endl; } } return 0; }AC Code
D題.Maximum Distributed Tree
D題是給出一棵樹,然後給出若干個乘積為k的質因子,問怎麼才能讓∑i=1|n-1∑j=i+1|n f(i,j)最大,其中f(u,v)為從u到v的鏈上的權值,這道題剛開始我覺得可能是樹鏈剖分,直接優先往重鏈上放prime factor,但是想了下這樣做似乎不妥,1e5您打算怎麼統計呢?之後隊友說是不是可以統計邊的使用次數,一語點醒夢中人,使用次數最多的優先安排大prime factor不就好了?那麼這個使用次數,通過手動模擬法發現,對於任意一點u,u以上的節點想要走到任意u為根的子樹節點,那麼必須要經過這條邊,次數也就好固定了,是子節點size * (n - 子節點size)。我給每條邊打上一個號,從1-n-1,然後開個陣列記錄,用堆優先選取次數達的,然後考慮n -1小於m的情況,將後面的貢獻全給第一個就行了,難得d的思路能這麼清晰,然後大草就發生了,陣列開小了tle,最後沒交上,賽後一發過了????這事兒怎麼老發生在我和weeping demon身上?????然後掉了36,下次再打回來就是了
#include <bits/stdc++.h> using namespace std; #define limit (500000 + 5)//防止溢位 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步兩步 #define EPS 1e-6 #define FASTIO ios::sync_with_stdio(false);cin.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a,b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout) #define debug(x) cout<<x<<endl typedef long long ll; typedef unsigned long long ull; inline ll read(){ ll sign = 1, x = 0;char s = getchar(); while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();} while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();} return x * sign; }//快讀 void write(ll x){ if(x < 0) putchar('-'),x = -x; if(x / 10) write(x / 10); putchar(x % 10 + '0'); } int sizes[limit], head[limit<<1] ,cnt; struct node{ int to, next, num; }edge[limit<<1]; void init(){ memset(head, -1, sizeof(head)); cnt = 0; } void add(int u ,int v,int num){ edge[cnt].to = v; edge[cnt].next = head[u]; edge[cnt].num = num; head[u] = cnt++; } ll dp[limit]; int n; void dfs(int u, int pre){ sizes[u] = 1; for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v != pre) { dfs(v, u); sizes[u] += sizes[v]; dp[edge[i].num] = (sizes[v]) * (n - sizes[v]); } } } int kase,m; ll fact[limit]; int main() { #ifdef LOCAL FOPEN; #endif FASTIO cin>>kase; const ll mod = 1e9 + 7; while (kase--){ cin>>n; init(); rep(i,1,n-1){ int x,y; cin>>x>>y; add(x,y,i); add(y,x,i); } cin>>m; rep(i,1,m){ cin>>fact[i]; } sort(fact + 1, fact + 1 + m, greater<>()); dfs(1,1); priority_queue<ll>q; rep(i,1,n-1){ q.push(dp[i]); } if(n -1 < m){//如果小於 rep(i,n,m){ ((fact[1] %= mod) *= (fact[i] %= mod)) %= mod; } m = n - 1; } ll ans = 0; rep(i ,1,m){ ans += (q.top() * fact[i]) % mod; ans %= mod; q.pop(); } while (q.size()){ ans += q.top(); ans %= mod; q.pop(); } cout<<(ans + mod) % mod<<endl; } return 0; }AC Code