首页 > 其他分享 >Codeforces Round #825 (Div. 2)

Codeforces Round #825 (Div. 2)

时间:2022-10-11 23:44:59浏览次数:72  
标签:int sum Codeforces long cin len 825 Div define

Codeforces Round #825 (Div. 2)

\(A\)
3min

#include<bits/stdc++.h>
using namespace std;
int a[105],b[105];
int main(){
	int t;cin>>t;
	while(t--){
		int n;cin>>n;
		for(int i=1;i<=n;++i)cin>>a[i];
		for(int i=1;i<=n;++i)cin>>b[i];
		int ans=0;
		for(int i=1;i<=n;++i){
			ans+=(a[i]!=b[i]);
		}
		int a1=0,b1=0;
		for(int i=1;i<=n;++i){
			a1+=(a[i]==1);
			b1+=(b[i]==1);
		}
		ans=min(ans,abs(a1-b1)+1);
		cout<<ans<<endl;
	}
	return 0;
}

\(B\)
7min

#include<bits/stdc++.h>
using namespace std;
int gcd(int x,int y){
	if(y==0)return x;
	return gcd(y,x%y);
}
int a[100005],b[100005];
int main(){
	int t;cin>>t;
	while(t--){
		int n;cin>>n;
		for(int i=1;i<=n;++i)cin>>a[i];a[n+1]=0;
		for(int i=2;i<=n;++i){
			b[i]=a[i-1]/gcd(a[i-1],a[i])*a[i];
		}
		b[1]=a[1];b[n+1]=a[n];
		int fl=1;
		for(int i=1;i<=n;++i){
			if(gcd(b[i],b[i+1])!=a[i])fl=0;
		}
		if(fl)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
}

\(C\)
6min

#include<bits/stdc++.h>
using namespace std;
int a[200005];
int main(){
	int t;cin>>t;
	while(t--){
		int n;cin>>n;
		for(int i=1;i<=n;++i)cin>>a[i];
		long long ans=0;int l=1;
		for(int i=1;i<=n;++i){
			l=max(i-a[i]+1,l);
			ans+=i-l+1;
		}
		cout<<ans<<endl;
	}
	return 0;
}

\(D\)
跟 \(C\) 同理, 设前 \(i\) 个 \(i-a[i]+1\) 的最大值为 \(Max_i\),答案即为 \(\sum i-Max_i+1\)。于是只要动态维护前缀最大值之和就好了。
于是我突然想起 楼房重建,于是赶紧 rush,虽然但是细节忘光了,比赛时没调出来。。。

需要注意的细节:
①节点 \(up\) 函数较为特殊,每次需要查询右儿子的信息。每次是相当于区间查询,但一定恰好完全覆盖当前节点,所以就可以直接利用节点信息计算。(考场上以为可能出现真子集,就没继续写了 QAQ

#include<bits/stdc++.h>
using namespace std;
#define N 200005
int a[N],Maxn[N];
struct seg{
	int l,r,maxn;
	long long sum;
}t[N<<3];
long long ques(int p,long long k){
	if(t[p].l==t[p].r)return max(t[p].sum,k);
	int mid=(t[p].l+t[p].r)>>1;
	if(k>=t[p<<1].maxn)return 1ll*(t[p<<1].r-t[p<<1].l+1)*k+ques(p<<1|1,k);
	else return ques(p<<1,k)+t[p].sum-t[p<<1].sum;
}
void up(int p){
	t[p].maxn=max(t[p<<1].maxn,t[p<<1|1].maxn);
	t[p].sum=t[p<<1].sum+ques(p<<1|1,t[p<<1].maxn);
}
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r;
	if(l==r){
		t[p].maxn=Maxn[l];
		t[p].sum=Maxn[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	up(p);
}
void change(int p,int l){
	if(t[p].l==t[p].r){
		t[p].maxn=Maxn[l];
		t[p].sum=Maxn[l];
		return ;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)change(p<<1,l);
	else change(p<<1|1,l);
	up(p);
}
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i){
		Maxn[i]=i-a[i]+1;
		Maxn[i]=max(Maxn[i],1);
	}
	build(1,1,n);
	int q;cin>>q;
	while(q--){
		int p,x,tmp;cin>>p>>x;
		long long ans=1ll*n*(n+1)/2+n;
		tmp=Maxn[p];
		Maxn[p]=max(1,p-x+1);
		change(1,p);
		ans-=t[1].sum;
		cout<<ans<<endl;
		Maxn[p]=tmp;
		change(1,p);
	}
	return 0;
}

附上码风较好的一份代码

//By Erinyes
#include<bits/stdc++.h>
#define maxn 200005
#define int long long
using namespace std;
int n,q;
int a[maxn];
struct sgt{
	struct node{int l,r,pos,sum;}t[maxn*4];
	#define l(p) t[p].l
	#define r(p) t[p].r
	#define pos(p) t[p].pos
	#define sum(p) t[p].sum
	#define len(p) (r(p)-l(p)+1)
	int getsum(int p,int k){
		if(len(p)==1) return max(k,pos(p));
		int mid=l(p)+r(p)>>1;
		if(pos(p<<1)<=k) return len(p<<1)*k+getsum(p<<1|1,k);
		else return getsum(p<<1,k)+sum(p)-sum(p<<1);
	}
	void update(int p){
		pos(p)=max(pos(p<<1),pos(p<<1|1));
		sum(p)=sum(p<<1)+getsum(p<<1|1,pos(p<<1));
	}
	void build(int p,int l,int r){
		l(p)=l,r(p)=r;
		if(l==r){pos(p)=sum(p)=max(l-a[l]+1,1ll);return;}
		int mid=l+r>>1;
		build(p<<1,l,mid),build(p<<1|1,mid+1,r); update(p);
	}
	void change(int p,int x,int k){
		if(len(p)==1){pos(p)=sum(p)=max(x-k+1,1ll);return;}
		int mid=l(p)+r(p)>>1;
		x<=mid?change(p<<1,x,k):change(p<<1|1,x,k); update(p);
	}
}s;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	s.build(1,1,n); cin>>q;
	while(q--){
		int x,k; cin>>x>>k;
		s.change(1,x,k);
		cout<<n*(n+1)/2-s.t[1].sum+n<<endl;
		s.change(1,x,a[x]);
	}
	return 0;
}

但其实考试的时候我也想过直接分讨,但没想清楚,考后才发现简单得一批
也是要维护前缀最大值之和,设修改后 \(p\) 右边第一个大于 \(Max_i\) 的为 \(q\) ,那么 \([1,p-1]\) 和 \([q,n]\) 都可以预处理(后者是用二分+ \(RMQ\) 维护),而 \([p,q-1]\) 可以直接计算,那不就结束了???

#include<bits/stdc++.h>
#define N 200005
using namespace std;
int a[N],f[N][20],T=19,e[21],lo[N];
long long pre_sum[N],suf_sum[N];
inline int get(int l,int r){
	if(l>r)return 1;
	int len=lo[r-l+1];
	return max(f[l][len],f[r-e[len]+1][len]);
}
inline int to(int x,int n){
	int l=x+1,r=n+1;
	while(l<r){
		int mid=(l+r)>>1;
		if(get(x+1,mid)>a[x])r=mid;
		else l=mid+1;
	}
	return l;
}
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
		a[i]=max(i-a[i]+1,1);
		f[i][0]=a[i];
	}
	a[0]=0,a[n+1]=n+1;f[n+1][0]=n+1;
	for(int i=1,maxn=0;i<=n;++i){
		maxn=max(maxn,a[i]);
		pre_sum[i]=pre_sum[i-1]+maxn;
	}
	e[0]=1;
	for(int i=1;i<=T;++i)e[i]=e[i-1]<<1;
	lo[1]=0;
	for(int i=2;i<N;++i)lo[i]=lo[i>>1]+1;
	for(int len=1;len<=T;++len){
		for(int i=1;i<=n+1-e[len]+1;++i){
			f[i][len]=max(f[i][len-1],f[i+e[len-1]][len-1]);
		}
	}
	for(int i=n;i;--i){
		int x=to(i,n);
		suf_sum[i]=suf_sum[x]+1ll*a[i]*(x-i);
	}
	int q;cin>>q;
	while(q--){
		int p,x,pre,ind;cin>>p>>x;
		long long ans=1ll*n*(n+1)/2+n,sum=0;
		pre=a[p];
		a[p]=max(p-x+1,get(1,p-1));
		ind=to(p,n);
		sum=pre_sum[p-1]+1ll*a[p]*(ind-p)+suf_sum[ind];
		ans-=sum;
		cout<<ans<<endl;
		a[p]=pre;
	}
	return 0;
}
		

标签:int,sum,Codeforces,long,cin,len,825,Div,define
From: https://www.cnblogs.com/Huster-ZHY/p/16783038.html

相关文章