Codeforces Round #750 (Div. 2) G. Kuzya and Homework

发布于 2021-11-11  821 次阅读


题目链接:https://codeforces.com/contest/1582/problem/F2

这题真的想偏了23333333。先说一个性质:如[l,r]不符合条件那么任意[l,r'](r'>r)肯定都不符合条件。因为 [l,r] 序列肯定是被一处或者多处阻断,如l不动,r增大阻断点还是没有消除。所以与r+1不可匹配的l肯定对r的不可匹配l有所继承,且要多于r的不可匹配数量。那么将r的可匹配集继承给r+1,然后再把不符合条件的都删掉。

真的是一个很牛逼的解法啊

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[1000055],pmi[1000555],prime[1000555],cnt;
char b[1000555];
vector<int>v[1000555],s;
int main(){

//质因数分解
	for(int i=2;i<=1e6;i++){
		if(!pmi[i]) pmi[i]=i,prime[++cnt]=i;
		for(int j=1;j<=cnt&&prime[j]*i<=1e6;j++){
			pmi[i*prime[j]]=prime[j];
			if(i%prime[j]==0) break;
		}
	}
	ll ans=0;
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	scanf("%s",b+1);
	for(int i=1;i<=n;i++){
		s.push_back(i);
		if(b[i]=='*'){
			for(int now=a[i];now!=1;now/=pmi[now]){
				v[pmi[now]].push_back(i);
			}
		}
		else{
			for(int now=a[i];now!=1;now/=pmi[now]){
				while(s.size()&&(v[pmi[now]].empty()||v[pmi[now]].back()<s.back())) s.pop_back();//弹出不符合条件的l
				if(v[pmi[now]].size()) v[pmi[now]].pop_back();//被除掉了
			}
		}
		ans+=s.size();//s是当前r=i符合条件的l集合
	}
	cout<<ans;
	return 0;
}

回忆这理想不够理想,沿途逛世间一趟只有向上