2023.7.6拷逝

T1

原题链接

对于区间 [l,r] ,答案是 max(cntr,cntl)x (其中 cntl,cntr 分别表示区间内左括号和右括号的数量, x 表示匹配的括号数量)。

首先考虑 max(cntr,cntl) 。该柿子可以转化成 (cntl+cntr+|cntrcntl|)/2 。前面的 cntl+cntr 非常好算,就是 i=1ni(ni+1) 。后面带绝对值的柿子怎么算呢?可以令 1 表示左括号, 1 表示右括号,求一个前缀和。然后将前缀和从小到大排序。对于排序后的前缀和 sum[i] ,它对答案的贡献是 i×sum[i]j=0j1sum[j] 。最后别忘了除以 2

再考虑 x 。我们用栈模拟匹配过程,如果发现一对匹配的括号(用 posl 表示左括号的位置, posr 表示右括号的位置),那么它会在 (nposr+1)×posl 个区间中出现。那么它对答案的贡献就是 (nposr+1)×posl

这样就可以在 O(n) 的复杂度内求得答案。

code:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
long long n,t,s[200005],stk[200005],r,ans;char a[200005];
int main(){
	freopen("common.in","r",stdin);
	freopen("common.out","w",stdout);
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%s",&n,a);
		ans=0;s[0]=0;
		for(int i=1;i<=n;++i)
			ans+=i*(n-i+1);
		for(int i=1;i<=n;++i){
			if(a[i-1]=='(') s[i]=s[i-1]+1;
			else s[i]=s[i-1]-1;
		}
		sort(s,s+n+1);
		long long sum=0;
		for(int i=0;i<=n;++i){
			ans+=s[i]*i-sum;
			sum+=s[i];
		}//cout<<ans<<endl;
		ans/=2;
		r=0;
		for(int i=0;i<n;++i){
			if(a[i]=='(')
				stk[++r]=i+1;
			else if(r>0){
				ans-=(n-i)*stk[r];//stk[r]~i+1
				--r;
			}
		}
		printf("%lld\n",ans);
	}
	fclose(stdin);fclose(stdout); 
	return 0;
}

T3

原题链接

首先有一个性质,任意两个三角形没有公共的部分,因为如果有公共部分一定不如把它们合起来更优。

然后就可以考虑 dp 。设 f[i] 表示考虑了 x 坐标在 [0,i] 内的所有点,存在一个右下角的横坐标为 i 的三角形时的最小代价。枚举上一个三角形的结束位置,则状态转移方程为:

f[i]=minj<i(f[j]+(ij1)×A+cost)

其中, cost 为所有满足 j<x<=i,1<=y<ki 的点的 c 之和。

然后用线段树维护即可。

code:

#include<iostream>
#include<vector>
#include<cstdio>
#define ll long long
using namespace std;
ll n,k,A,ans,x,y,z,cnt[200005],f[200005];
struct node{
	int l,r;ll minn,lazy;
} p[800005];
struct node2{
	int x;ll w;
};vector <node2> a[200005];
void build(int u,int l,int r){
	p[u].l=l;p[u].r=r;
	if(l==r)
		return ;
	int mid=(l+r)>>1;
	build(u<<1,l,mid);build(u<<1|1,mid+1,r);
}
void push_down(int u){
	p[u<<1].minn+=p[u].lazy;
	p[u<<1|1].minn+=p[u].lazy;
	p[u<<1].lazy+=p[u].lazy;
	p[u<<1|1].lazy+=p[u].lazy;
	p[u].lazy=0;
}
void add(int u,int l,int r,ll w){
	if(p[u].l>=l&&p[u].r<=r){
		p[u].minn+=w;p[u].lazy+=w;
		return ;
	}
	push_down(u);
	int mid=(p[u].l+p[u].r)>>1;
	if(mid>=l)
		add(u<<1,l,r,w);
	if(mid<r)
		add(u<<1|1,l,r,w);
	p[u].minn=min(p[u<<1].minn,p[u<<1|1].minn); 
}
ll ask(int u,int l,int r){
	if(p[u].l>=l&&p[u].r<=r)
		return p[u].minn;
	push_down(u);
	int mid=(p[u].l+p[u].r)>>1;ll re=1e18;
	if(mid>=l)
		re=min(re,ask(u<<1,l,r));
	if(mid<r)
		re=min(re,ask(u<<1|1,l,r));
	return re;
}
int main(){
	ans=1e18;
	scanf("%lld%lld%lld",&n,&k,&A);
	build(1,1,k+2);
	for(int i=1;i<=n;++i){
		scanf("%lld%lld%lld",&x,&y,&z);
		a[y].push_back((node2){x,z});
		if(x+y!=k)
			cnt[x]+=z;
	}
	for(int i=0;i<=k;++i){
		for(int j=0;j<a[k-i].size();++j)
			add(1,1,a[k-i][j].x+1,-a[k-i][j].w);
		add(1,1,i+1,cnt[i]);
		if(i!=0)
			add(1,1,i,A);
		f[i]=ask(1,1,i+1);
		add(1,i+2,i+2,f[i]);
	}
	printf("%lld\n",f[k]);
	fclose(stdin);fclose(stdout);
	return 0;
}

T4

原题链接

将第1,2个,第3,4个相同的数之间连边;将序列中第1,2个,第3,4个相同的数之间连边。

然后会形成若干个偶数环,对于每个环,让其中的数交替出现在集合1,集合2。

code:

#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
using namespace std;
map <int,int> u;
vector <int> p[400005];
int tot,m,n[400005],x,at[400005];bool vis[400005];
void dfs(int x,int num){
	vis[x]=1;
	if(!at[x])
		at[x]=num;
	for(int i=0;i<p[x].size();++i)
		if(!vis[p[x][i]])
			dfs(p[x][i],num^1);
}
int main(){
	scanf("%d",&m);
	for(int i=1;i<=m;++i){
		scanf("%d",&n[i]);
		for(int j=1;j<=n[i];++j){
			scanf("%d",&x);
			++tot;
			if(!(j&1)){
				p[tot].push_back(tot-1);
				p[tot-1].push_back(tot);
			}
			if(!u[x])
				u[x]=tot;
			else{
				int tmp=u[x];u.erase(x);
				p[tmp].push_back(tot);
				p[tot].push_back(tmp);
			}
		}
	}
	if(u.size())
		printf("NO\n");
	else{
		printf("YES\n");
		for(int i=1;i<=tot;++i)
			if(!vis[i])
				dfs(i,1); 
		int tot2=0;
		for(int i=1;i<=m;++i){
			for(int j=1;j<=n[i];++j){
				++tot2;
				if(at[tot2]) printf("R");
				else printf("L");
			}
			printf("\n");
		}
	}
	return 0;
} 
posted @   andy_lz  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示