Codeforces Round #816 (Div. 2)

Codeforces Round #816 (Div. 2)

A,B没做

C. Monoblock

大意

我们可以将一组数组相同的数字进行分块,定义其价值为分的块数,如[1,1,1] 可以分成一块,[1,7,7,7,7,7,7,7,9,9,9,9,9,9,9,9,9]是3块,被分成了 [1], [7,7,7,7,7,7,7], and 9,9,9,9,9,9,9,9,9];

\(1e5\)次询问,每次询问修改数组的一个数字,求修改后,该数组的所有子段的分块和。

分析

观察得到,

如果前后项互异的话,\(ans=\sum_{1}^{n}i*(n-i+1)\),则前后项相同的话,此项贡献为\(i\),因此只需要维护其前后项是否相同即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7;
typedef long long ll;
ll a[N];
int main() {
	int n,m;
	cin >> n >> m;
	for(int i = 1 ; i <= n ; i++) {
		cin >> a[i];
	}
	ll ans = 0;
	for(int i = 1 ; i <= n ; i++) {
		ll r = 1;
		if(a[i]!=a[i+1] && i != n) {
			r = n-i*1ll+1;
		}
		ans += r*i;
	}
	for(ll i = 1 ; i <= m ; i++ )  {
		ll ii,x;
		cin >> ii >> x;
		if(a[ii]!=a[ii-1] && ii !=1) {
			if(a[ii-1]==x) {
				ans -= (ii-1)*(n-ii+2);
				ans += (ii-1)*1; 
			}
		}
		if(a[ii]==a[ii-1] && ii!=1) {
			if(a[ii-1]!=x) {
				ans -= (ii-1)*1; 
				ans += (ii-1)*(n-ii+2);
			}
		}
		if(a[ii]!=a[ii+1] && ii != n) {
			if(a[ii+1]==x) {
				ans -= (ii)*(n-ii+1);
				ans += (ii)*1; 
			}
		}
		if(a[ii]==a[ii+1] && ii != n) {
			if(a[ii+1]!=x) {
				ans -= (ii)*1; 
				ans += (ii)*(n-ii+1);
			}
		}
		a[ii] = x;
		printf("%lld\n",ans);
	}
}

D. 2+ doors

给定\(Q\)条线索,\(i,j,x\)表示\(a[i]|a[j]=x\),求原序列最小字典序的可能性。

思路

\(n\)个数字全置1,读入线索时再\(\&x\),然后得到最大。将所有1置0检测是否成立即可得到最小。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+7;
const ll inf = (1ll<<31)-1;
ll a[N];
vector<pair<ll,ll> >e[N];
int main() {
	ll n,q;
	cin >> n >> q ;
	for(int i = 1 ; i <= n ; i++)
		a[i] = inf;
	for(int i = 1 ; i <= q ; i++) {
		ll l,r,x;
		scanf("%lld%lld%lld",&l,&r,&x);
		a[l]&=x;
		a[r]&=x;
		e[l].push_back({r,x});
		e[r].push_back({l,x});
	}
	for(int i = 1 ; i <= n ; i++) {
		for(int j = 0 ; j <= 30 ; j++) {
			if((1<<j)&a[i]) {
				bool flag = 1;
				for(auto &t:e[i]) {
					ll x = t.first;
					ll y = t.second;
					if((a[x]|a[i]-(1<<j))!=y || x==i) {
						flag = 0;
						break;
					}
				}
				if(flag)
					a[i]-=(1<<j);
			}
		}
	}
	for(int i = 1 ; i <= n ; i++)
		printf("%lld ",a[i]);
}
posted @ 2022-08-22 14:40  seekerHeron  阅读(63)  评论(3)    收藏  举报