pyyzDay18

模拟赛(掉大分)

T1 [KOI 2022 Round 1] 鹅卵石

大炮预处理

T2 [POI 2018 R2] 自行车道 Bike paths

缩点板子+树形DP

#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int> tu[100005],to[100005];
int vis[100005],dfn[100005],low[100005],st[100005],top,col,cnt,sum[100005],bel[100005],ans[100005],vi[100005];
void dfs(int x){
	low[x]=dfn[x]=++cnt;
	st[++top]=x;
	vis[x]=1;
	for(auto ed:tu[x]){
		if(!dfn[ed]){
			dfs(ed);
			low[x]=min(low[x],low[ed]);
		}
		else if(vis[ed]) low[x]=min(low[x],dfn[ed]);
	}
	if(low[x]==dfn[x]){
		int v=-1;
		col++;
		while(true){
			v=st[top];
			top--;
			vis[v]=0;
			bel[v]=col;
			sum[col]++;
			if(v==x) break;
		}
	}
}
void dfs2(int x,int fa){
	if(vi[x]) return ;
	vi[x]=1;
	for(auto ed:to[x]){
		if(ed==fa) continue;
		dfs2(ed,x);
		ans[x]+=ans[ed];
	}
	ans[x]+=sum[x];
}
signed main() {
	//	freopen("bike.in","r",stdin);
	//	freopen("bike.out","w",stdout);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		tu[u].push_back(v);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]) dfs(i);
	}
	for(int i=1;i<=n;i++){
		int bi=bel[i];
		for(auto ed:tu[i]){
			int bed=bel[ed];
			if(bed!=bi){
				to[bi].push_back(bed);
			}
		}
	}
	for(int i=1;i<=col;i++){
		if(!vi[i]){
			dfs2(i,0);
		}
	}
	for(int i=1;i<=n;i++){
		cout<<ans[bel[i]]-1<<'\n';
	}
	return 0;
}

T3 [POI 2016 R3] 巡游 Parade

树形DP

T4 [POI 2011] TEM-Temperature

双指针+ST表/单调队列

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int l[1000005],st[1000005][25],r[1000005];
int maxx(int l,int r){
	int logg=__lg(r-l+1);
	return max(st[l][logg],st[r-(1<<logg)+1][logg]);
}
signed main(){
	int n=read();
	memset(st,-0x3f,sizeof(st));
	for(int i=1;i<=n;i++){
		l[i]=read();
		r[i]=read();
		st[i][0]=l[i];
	} 
	for(int i=1;i<=20;i++){
		for(int j=1;j<=n;j++){
			if(j+(1<<i-1)<=n) st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
		}
	}
	int ll=1,rr=1;
	int ans=0;
	while(rr<=n){
		while(ll<=rr&&r[rr]<maxx(ll,rr)) ll++;
		ans=max(ans,rr-ll+1);
		rr++;
	}	
	cout<<ans<<'\n';
	return 0;
}

T5 [POI 2020/2021 R2] 收拾背包 / Pakowanie plecaka

数据结构优化DP

正难则反

考虑删除几个点

设 sn=∑ai(i+1~n)

若点i可删,则s_i+1<ai

设di=s_i+1-ai

考虑将di<0的数扔进大根堆里

每次取最大的(因为要求值最小)进行删除

然后进行区间-ai

判断是否有新的di<0加入堆

线段树维护

posted @ 2025-08-23 17:23  gbrrain  阅读(5)  评论(0)    收藏  举报