Educational Codeforces Round 161 (Rated for Div. 2)

A. Tricky Template
长度为n的字符串a,b,c(均为小写字母)
一个模板字符串t
匹配:如果模板是小写字母,那么字符串要相同,如果模板是大写字母,就不能相同
问是否存在模板t使得a和b与t匹配,t和c不匹配
坑点:YES,NO

如果c总和a和b的其中一个相同,那么就NO

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
string a,b,c;
void solve() {
	cin>>n;
	cin>>a>>b>>c;
	for(int i=0;i<n;i++){
		if(!(c[i]==a[i]||c[i]==b[i])){
			cout<<"YES"<<endl;
			return;
		}
	}
	cout<<"NO"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Forming Triangles
长度为n的数组a(范围在0到n)
一共有n根木棒(编号1到n),第i根长度为2的ai次方
从n根中选取三根,组成一个三角形
问有几种方式组成三角形(两边之和大于第三边)

与顺序无关,排个序

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=3e5+10;
int a[N];
int sum[N];
int n;
int C2(int x){
	return x*(x-1)/2;
}
int C3(int x){
	return x*(x-1)*(x-2)/6;
}
void solve() {
	cin>>n;
	memset(sum,0,sizeof sum);//sum[i]表示小于i的有几个数
	map<int,int>mp;
	for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]++;
	sort(a+1,a+1+n);
	for(int i=1;i<=n-1;i++){
		if(a[i+1]!=a[i]) sum[a[i+1]]=i;
	}
//	for(int i=1;i<=n;i++) cout<
//	cout<
	int ans=0;
	for(auto v:mp){
		if(v.second>=2){
			ans+=sum[v.first]*C2(v.second);
			if(v.second>=3) ans+=C3(v.second); 
		}
	}
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C. Closest Cities
长度为n的数组a,数的范围为[0,1e9]
共m行询问,每次给定两个整数x和y,计算从城市x到城市y需要花费最少的硬币数
共m座城市,位于ai,按升序排列
对于一座城市,离它最近的城市是唯一的

操作:从城市x到y,花费它们距离的金币或者到离x最近的城市(唯一的)花费1金币

x和y在两个方向,x朝着y方向走,一直走最近,直到最近的是往回走,千万不能走回头路,此时直接花费距离金币到y
并查集不可行,并查集不能有环,那就用两个并查集,往右的和往左的,但是这样是错的,因为并不是走到并查集的头就断了,可以先利用城市距离过去再继续走最近城市

由于不能走回头路,所以我们利用一个前缀和以及后缀和就可以了,如果可以走最近城市那么就加1,否则就加两城市之间的距离
不能走回头路,然后如果能走最近城市就走最近城市,如果不能走就花费距离金币,这样花费代价是最小的

trick:

1.多次询问区间以及不能走回头路,考虑方向为前缀和

2.并查集是不能出现环的

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int a[N];
int pre[N],last[N];
int n,m;
void solve() {
	cin>>n;
	memset(pre,0,sizeof pre);
	memset(last,0,sizeof last);
	for(int i=1;i<=n;i++) cin>>a[i];
	//前缀和
	for(int i=1;i<n;i++){
		if(i==1) pre[i+1]=pre[i]+1;
		else{
			if(abs(a[i]-a[i+1])<abs(a[i]-a[i-1])) pre[i+1]=pre[i]+1;
			else pre[i+1]=pre[i]+abs(a[i]-a[i+1]);
		}
	}
	//后缀和
	for(int i=n;i>1;i--){
		if(i==n) last[i-1]=last[i]+1;
		else{
			if(abs(a[i]-a[i-1])<abs(a[i]-a[i+1])) last[i-1]=last[i]+1;
			else last[i-1]=last[i]+abs(a[i]-a[i-1]);
		}
	}
	cin>>m;
	while(m--){
		int x,y;
		cin>>x>>y;
		if(x<y) cout<<pre[y]-pre[x]<<endl;
		else cout<<last[y]-last[x]<<endl;
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++)