Codeforces Global Round 1

2022/3/4

A. Parity

题意:
n = a 1 ∗ b k − 1 + a 2 ∗ b k − 2 + . . . + a k n=a_1*b^{k-1}+a_2*b^{k-2}+...+a_k n=a1bk1+a2bk2+...+ak的奇偶性。
题解:
考虑b的奇偶性,若b为偶数,则前k-1项必为偶数,此时只用判断 a k a_k ak奇偶性。若b为奇数,n的奇偶性只与 ∑ i − 1 k a i \sum_{i-1}^ka_i i1kai有关。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 300200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int a[maxn];
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int b,k;
	cin>>b>>k;
	for(int i=1;i<=k;i++)cin>>a[i];
	if(b%2==0){
		if(a[k]%2)cout<<"odd";
		else cout<<"even"; 
	}
	else{
		int sum=0;
		for(int i=1;i<=k;i++){
			sum+=a[i]%2;
		}
		sum%=2;
		if(sum)cout<<"odd";
		else cout<<"even";
	}
    return 0;
}

B. Tape

题意:
有一个m长的棍子,有n除断裂,你有k个胶带,求所需胶带的最小长度。
题解:
考虑1个胶带若匹配一个断裂,所需长度为1,还剩下n-k个断裂,每个断裂所需要的贡献为 p o s i − p o s i − 1 pos_i-pos_{i-1} posiposi1。对差值排序,取最小的n-k个贡献。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 300200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int a[maxn];	
int n,m,k;
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)cin>>a[i];
	vector<int>v;
	for(int i=2;i<=n;i++)v.push_back(a[i]-a[i-1]-1);
	sort(v.begin(),v.end());
	int ans=0;
	for(int i=0;i<n-k;i++)ans+=v[i];
	cout<<ans+n<<"\n";
    return 0;
}

C. Meaningless Operations

题意:
f ( a ) = m a x 0 < b < a g c d ( a ⨁ b , a & b ) f(a)=max_{0<b<a}gcd(a\bigoplus{b},a\&b) f(a)=max0<b<agcd(ab,a&b)
题解:
考虑 a ⨁ b = ( a ∣ b ) − ( a & b ) , g c d ( a ⨁ b , a & b ) = g c d ( a ∣ b , a & b ) a\bigoplus{b}=(a|b)-(a\&b),gcd(a\bigoplus{b},a\&b)=gcd(a|b,a\&b) ab=(ab)(a&b),gcd(ab,a&b)=gcd(ab,a&b)
若a不为 2 n − 1 2^n-1 2n1,则 a ∣ b = 2 n − 1 , a & b = 0 a|b=2^n-1,a\&b=0 ab=2n1,a&b=0时,gcd最大为a。
若a为 2 n − 1 2^n-1 2n1,则b无论取什么, a ∣ b = a a|b=a ab=a a & b a\&b a&b可以取[1,a-1].gcd最大时就是a/(除了a的最大的因子)。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 300200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}

int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int q;
	cin>>q;
	while(q--){
		ll nn;
		cin>>nn;
		ll x=1;
		while(x<=nn)x*=2ll;
		if(x-1ll==nn){
			ll n=nn;
			vector<int>ans;
			for(int i=2;i*i<=n;i++){
				if(n%i==0){
					while(n%i==0)ans.push_back(i),n/=i;
				}
			}
			if(n>1)ans.push_back(n);
			sort(ans.begin(),ans.end());
			cout<<nn/ans[0]<<"\n";
		}
		else cout<<x-1ll<<"\n";
	}
    return 0;
}

D. Jongmah

题意:
有n个牌,牌上的数字为[1,m],三个一样的数字或者三个连续的数字可以凑为一组,问最多可以凑多少组。
题解:
对于每张牌,有四个方案, ( i , i , i ) , ( i , i + 1 , i + 2 ) , ( i − 1 , i , i + 1 ) , ( i − 2 , i − 1 , i ) (i,i,i),(i,i+1,i+2),(i-1,i,i+1),(i-2,i-1,i) (i,i,i),(i,i+1,i+2),(i1,i,i+1),(i2,i1,i)
后面三个方案数不会超过3,一旦超过3,那么每张牌可以自己三个一组。
考虑dp。
dp[i][j][k]表示到第i张牌时,使用3方案j个,使用2方案k个。
dp[i][k][l]=dp[i-1][j][k]+l+(num[i]-j-k-l)/3.

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 1000200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
ll dp[maxn][4][4],num[maxn];
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1,x;i<=n;i++){
		cin>>x;
		num[x]++;
	}
	for(int i=1;i<=m;i++){
		for(int j=0;j<3;j++){
			for(int k=0;k<3;k++){
				for(int l=0;l<3&&j+k+l<=num[i];l++){
					dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+l+(num[i]-j-k-l)/3);
				}
			}
		}
	}
	cout<<dp[m][0][0];
    return 0;
}

E. Magic Stones

题意:
有两个数组 c , t c,t c,t.对于i为[2,n-1]的数,你可以令 c i = c i − 1 + c i + 1 − c i c_i=c_{i-1}+c_{i+1}-c_i ci=ci1+ci+1ci
问能否将 c c c数组变为 t t t数组.
题解:
一次操作后,实际上 c i c_i ci仅仅对于 ( c i − 1 + c i + 1 ) / 2 (c_{i-1}+c_{i+1})/2 (ci1+ci+1)/2对称.
也就是差值 c i + 1 − c i , c i − c i − 1 c_{i+1}-c_i,c_i-c_{i-1} ci+1ci,cici1对换。但是差值不会改变,数量也不变,只需要比较下差值是否完全一致,以及 c 1 = = t 1 c_1==t_1 c1==t1

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 1000200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int a[maxn],b[maxn];
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n;
	vector<int>ans1,ans2;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=2;i<=n;i++){
		ans1.push_back(a[i]-a[i-1]);
		ans2.push_back(b[i]-b[i-1]);
	}
	sort(ans1.begin(),ans1.end());
	sort(ans2.begin(),ans2.end());
	if(a[1]==b[1]&&ans1==ans2)cout<<"Yes\n";
	else cout<<"No\n";
    return 0;
}

F. Nearest Leaf

题意:
有一颗以1为根的树,两点之间的距离就是边权相加的和。询问q次,每次问所有dfs序在[l,r]内的叶子节点距离v结点的最短路径。
题解:
对与每个点u,若叶子结点v是他的儿子,他的路径就是 d i s ( u , v ) = d i s ( 1 , v ) − d i s ( 1 , u ) dis(u,v)=dis(1,v)-dis(1,u) dis(u,v)=dis(1,v)dis(1,u),否则 d i s ( u , v ) = d i s ( 1 , v ) + d i s ( 1 , u ) dis(u,v)=dis(1,v)+dis(1,u) dis(u,v)=dis(1,v)+dis(1,u)。判断是否是儿子结点可以用dfs序来判断,贡献用线段树区间维护,离线查询。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 500200
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int n,m,cnt,l[maxn],r[maxn],siz[maxn];
ll ans[maxn],a[maxn],dis[maxn];
vector<pair<int,int> >g[maxn];
struct node{
	int id,l,r;
	node(int a,int b,int c){
		id=a;
		l=b;
		r=c;
	}
};
vector<node >q[maxn];
void dfs1(int u){
	l[u]=++cnt;
	siz[u]=1;
	for(auto &it:g[u]){
		int v=it.first,w=it.second;
		dis[v]=dis[u]+w;
		dfs1(v);
		siz[u]+=siz[v];
	}
	r[u]=l[u]+siz[u]-1;
}
ll tree[maxn<<2];
ll lazy[maxn<<2];
void pushup(int id){
	tree[id]=min(tree[id<<1],tree[id<<1|1]);
}
void pushdown(int id){
	if(!lazy[id])return ;
	tree[id<<1]+=lazy[id];
	tree[id<<1|1]+=lazy[id];
	lazy[id<<1]+=lazy[id];
	lazy[id<<1|1]+=lazy[id];
	lazy[id]=0;
	return;
}
void build(int id,int l,int r){
	if(l==r){
		tree[id]=a[l];
		return ;
	}
//	printf("%d %d\n",l,r);
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	pushup(id);
}
void update(int id,int l,int r,int lx,int ly,ll val){
	if(l>=lx&&r<=ly){
		tree[id]+=val;
		lazy[id]+=val;
		return ;
	}
	pushdown(id);
	int mid=(l+r)>>1;
	if(mid>=lx)update(id<<1,l,mid,lx,ly,val);
	if(mid<ly)update(id<<1|1,mid+1,r,lx,ly,val);
	pushup(id);
}
ll query(int id,int l,int r,int lx,int ly){
	if(l>=lx&&r<=ly)return tree[id];
	pushdown(id);
	int mid=(l+r)>>1;
	ll ans=inf;
	if(mid>=lx)ans=min(ans,query(id<<1,l,mid,lx,ly));
	if(mid<ly)ans=min(ans,query(id<<1|1,mid+1,r,lx,ly));
	return ans;
}
void dfs2(int u){
	for(auto &it:q[u]) {
		ans[it.id]=query(1,1,n,it.l,it.r);
	}
	for(auto &it:g[u]){
		int v=it.first,w=it.second;
		update(1,1,n,1,n,w);
		update(1,1,n,l[v],r[v],-2*w);
		dfs2(v);
		update(1,1,n,1,n,-w);
		update(1,1,n,l[v],r[v],2*w);
	}
}
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>n>>m;
	for(int i=2,u,v;i<=n;i++){
		cin>>u>>v;
		g[u].push_back(make_pair(i,v));
	}
//	for(auto &x:g)sort(x.begin(),x.end());
	for(int i=1,v,l,r;i<=m;i++){
		cin>>v>>l>>r;
		q[v].push_back({i,l,r});
	}	
	dfs1(1);
//	printf("111\n");
	for(int i=1;i<=n;i++){
		if(siz[i]==1)a[i]=dis[i];
		else a[i]=inf;
	} 
	build(1,1,n);
//	printf("2222\n");
	dfs2(1);
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<"\n";
	}
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值