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加入堆
线段树维护

浙公网安备 33010602011771号