Codeforces Round 506 (Div. 3)

目录

A. Many Equal Substrings

B. Creating the Contest

C. Maximal Intersection

D. Concatenated Multiples

E. Tree with Small Distances

F. Multicolored Markers

A. Many Equal Substrings

字符串的叠加问题只要是前面的和后面的一样的话前面的就不用再出现了只需要找到最大的出现的前面和后面即可,所以我们选择直接暴力即可(数据范围较小)

void solve(){
    
    cin>>n>>m;
    string s; cin>>s;
    int pos = 0;
	for(int i=0;i<n;i++)
		if(s.substr(0,i)==s.substr(n-i,i)) pos=i;
	string add = s.substr(pos);
	cout<<s;
	m--;
	while(m--) cout<<add;
    cout<<endl;
    return ;
}

B. Creating the Contest

明显的具有双指针的性质所以我们直接使用双指针即可

void solve(){
    
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans  = 0;
    for(int i=1;i<=n;i++){
    	int j = i;
    	while(j+1<=n and a[j+1]<=2*a[j]) j++;
    	ans = max(ans,j-i+1);
    	i=j;
    }
    cout << ans << endl;
    return ;
}

C. Maximal Intersection

左右区间的覆盖我们考虑使用multiset来维护,然后找左右匹配就可以知道其实就是区间的交集

void solve(){
    
    cin>>n;
    multiset<int> L,R;
    for(int i=1;i<=n;i++){
    	int l,r; cin>>l>>r;
    	L.insert(l);
    	R.insert(r);
    	seg[i]={l,r};
    }
    int ans = 0;
    for(int i=1;i<=n;i++){
    	auto [l,r]=seg[i];
    	L.erase(L.find(l));
    	R.erase(R.find(r));
    	int maxl= *L.rbegin();
    	int minr= *R.begin();
    	ans = max(ans,minr-maxl);
    	L.insert(l);
    	R.insert(r);
    }
    cout << ans << endl;
    return ;
}

D. Concatenated Multiples

区间的拼接,我们可以发现最后是由两个部分组成一个是前面的一个是后面的,前面的贡献来源于本身以及后面数的数位,所以我们考虑预处理每一个数后面添加数的位数之后的贡献,然后对于后面的数只需要去找这个数在后面的时候的答案贡献即可(注意自己和自己拼接)

map<int,int> mp[15];
int t,n,m;
int a[N];

int ten[20];

void solve()
{
 	cin>>n>>m;
 	for(int i=1;i<=n;i++) cin>>a[i];
 	
	ten[0]=1;
	for(int i=1;i<=15;i++) ten[i]=10*ten[i-1];
	
	for(int i=1;i<=10;i++)
		for(int j=1;j<=n;j++){
			int x=a[j]%m*(ten[i]%m)%m;// 我多了这么多%的数需要+mod m 为x的数
			//  表示我在这个数后面需要 衔接 的数的余数
			mp[i][(m-x)%m]++;
		} 	
	
	int ans=0;
	
	for(int i=1;i<=n;i++){
		int cnt=0;
		int x=a[i];
		while(x) x/=10,cnt++;
		ans+=mp[cnt][a[i]%m];
		string s=to_string(a[i]);
		s=s+s;
		int ok=0;
		
		for(int i=0;s[i];i++){
			ok=(ok*10+(s[i]-'0'))%m;
		}
		if(!ok) ans--;
	}
	cout<<ans<<endl;
    
    return ;
}

E. Tree with Small Distances

我们有个明显的贪心策略就是从权重最大的人的父节点开始操作,如果他的父节点被标记了的话就直接把他父节点的儿子节点也标记,同时注意如果可以在dfs外操作的尽量在dfs外操作否则就一定要理清楚是不是可以递归的,此题我们采用外面取操作即可

ector<int> g[N];
int f[N],d[N];
bitset<N> st;
void dfs(int u,int fa){
	if(~fa){
		d[u]=d[fa]+1;
		f[u]=fa;
	}
	for(auto&v:g[u]){
		if(v==fa) continue;
		dfs(v,u);
	}
}
void solve(){
    
    cin>>n;
    for(int i=1;i<n;i++){
    	int a,b; cin>>a>>b;
    	g[a].push_back(b);
    	g[b].push_back(a);
    }
    dfs(1,-1);
    priority_queue<PII> q;
    for(int i=1;i<=n;i++) if(d[i]>2) q.push({d[i],i});
    int ans = 0;
    while(!q.empty()){
    	auto [d,v]=q.top(); q.pop();
    	if(st[v]) continue;
    	ans ++ ;
    	st[v]= true;
    	int u = f[v];
    	st[u]=true;
    	for(auto&v:g[u]) st[v]=true;
    }
    cout << ans << endl;
    return ;
}

F. Multicolored Markers

我们直接按照题目意思去模拟即可,不要自己想到啥就是啥,我们可以知道如果说构造的矩形中能包括a构成的一个小矩形或者包括b的小矩形的话就是ok的所以直接检查即可

void solve()
{
    int a,b; cin>>a>>b;
    int sum=a+b;
    
    vector<PII> A,B;
    
    for(int i=1;i<=a/i;i++){
    	if(a%i==0){
    		A.push_back({i,a/i});
    	}
    } 
    for(int i=1;i<=b/i;i++){
    	if(b%i==0){
    		B.push_back({i,b/i});
    	}
    }
    
    auto check = [&](int x,int y){
    	for(auto&[a,b]:A){
    		if(x>=a && y>=b) return true;
    	}
    	for(auto&[a,b]:B){
    		if(x>=a && y>=b) return true;
    	}
    	return false;
    };
    
    int ans=3e18;
    for(int i=1;i<=sum/i;i++){
    	if(sum%i==0){
    		if(check(i,sum/i)){
    			ans=min(ans,2*(i+sum/i));
    		}
    	}
    }
    cout<<ans<<endl;
    
    return ;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值