【题解】240914ABC371

T1:模拟

void solve(){
	int a[3];
	char s[3];
	cin >> s[0] >> s[1]>>s[2];
	if(s[0]=='>'){
		if(s[1]=='>'){
			if(s[2]=='>'){// >>>
				cout <<"B"<<endl;
			}
			else{//>><
				cout << "C"<<endl;
			}
		}
		//><>不存在
		else{//><<
			cout <<"A"<<endl;
		}
	}
	else{
		if(s[1]=='>'){//<>
			if(s[2]=='>'){//<>>
				cout <<"A"<<endl;
			}
		}
		else{
			if(s[2]=='>'){
				cout <<"C"<<endl;
			}
			else{
				cout <<"B"<<endl;
			}
			
		}
	}
}

T2:找每次如果是M且之前没有过M的,模拟即可

void solve(){
	cin >> n >> m;
	for(int i=0;i<m;i++){
		cin >> a[i] >> b[i];
	}
	for(int i=0;i<m;i++){
		if(b[i]=='M'){
			++st[a[i]-1];
			if(st[a[i]-1]==1){
				yes;
				continue;
			}
		}
		no;
	}
}

T3:图的同构

VVI add(VPII e, int n) {
	VVI jj(n, VI(n, 0));
	for (auto ee : e) {
		int u = ee.first;
		int v = ee.second;
		jj[u][v] = 1;
		jj[v][u] = 1;
	}
	return jj;
}

int fc(VVI gg,VVI hh,VVI c,VI p) {
	int tot = 0;
	for (int i = 0; i < gg.size(); ++i) {
		for (int j = i + 1; j < N; ++j) {
			int u = p[i];
			int v = p[j];
			if (gg[u][v] != hh[i][j]) {
				tot += c[i][j];
			}
		}
	}
	return tot;
}

void solve(){
	int n;
	cin >> n;
	int g;
	cin >> g;
	VPII eg(g+10);
	for (int i = 0; i < g; i++) {
		int u, v;
		cin >> u >> v;
		eg[i] = {u - 1, v - 1};
	}
	int h;
	cin >> h;
	VPII eh(h);
	for (int i = 0; i < h; i++) {
		int a, b;
		cin >> a >> b;
		eh[i] = {a - 1, b - 1}; 
	}
	
	VVI c(n, VI(n, 0));
	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			cin >> c[i][j];
		}
	}
	VVI gg = add(eg, n);
	VVI hh = add(eh, n);
	VI p(n);
	iota(p.begin(), p.end(), 0);
	int ans = 0x3f3f3f3f;
	ans = min(ans, fc(gg, hh, c, p));
	while (next_permutation(p.begin(), p.end())){
		ans = min(ans, fc(gg, hh, c, p));
	}
	cout << ans << endl;
}

T4:阅读题意很显然是使用前缀和,但问题在于a[i]范围是LL如果按照普通方法开前缀肯定会爆MLE,结局的两种方法是在LL上使用二分,其次是离散化,这里提供LL的vector版本

void solve(){
	cin >> n;	
	VI x;
	VI p;
	for (int i = 0; i < n; i++) {
		int xx;
		cin >> xx;
		x.push_back(xx);
	}
	for (int i = 0; i < n; i++) {
		int pp;
		cin >> pp;
		p.push_back(pp);
	}
	for (int i = 0; i < n; ++i) {
		s[i + 1] = s[i] + p[i];
	}
	cin >> q;
	while (q--) {
		int L, R;
		cin >> L >> R;
		
		VI::iterator itl = lower_bound(x.begin(), x.end(), L);
		VI::iterator itr = upper_bound(x.begin(), x.end(), R);
		
		int l = distance(x.begin(), itl);
		int r = distance(x.begin(), itr) - 1;
		
		if (l <= r && l < n && r >= 0) {
			LL ans = s[r + 1] - s[l];
			cout << ans <<endl;
		} else {
			cout << 0 << endl;
		}
	}
}

T5:首先想到了滑动窗口和unordered_set的Onlogn,但实际会On2TLE

void solve(){
	cin >> n;
	read(a,n);
	LL ans = 0;
	for (int i = 0; i < n; i++) {
		unordered_set<int> alls;
		int temp = 0;
		for (int j = i; j < n; j++) {
			if (alls.find(a[j]) == alls.end()) {
				alls.insert(a[j]);
				temp++;
			}
			ans += temp;
		}
	}
	
	cout << ans << endl;
}

正解:考虑互补事件先计算不包含 i 的子数组的个数,然后从所有数组中减去总和。在 A 的两端插入 i,按升序排列的索引 x 和 Ax = i 就表示为 x=(x0,x1....x_Ci+1 = N+1)不包含 i 的子数组数等于

(左端为 x0+1 或更大,右端为 x1-1 或更小的子数组的个数)+ (左端大于等于 x1+1 且右端小于等于 x2-1 的子数组个数)+...........+ (左端为 x{Ci}+1 或以上,右端为 x{Ci+1}-1 或以下的子数组个数)

void solve(){
  int n;
  LL ans = 0;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    ans += 1LL * (i - p[a[i]]) * (n - i + 1);
    p[a[i]] = i;
  }
  cout << ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值