Noip模拟41 2021.8.16

T1 你相信引力吗

对于区间的大小关系问题,往往使用单调栈来解决

这道题的优弧和劣弧很烦,考虑将其等价的转化

由于所有的合法情况绕过的弧都不会经过最高的冰锥,

又因为环可以任意亲定起点,这样可以直接把最大的点当作起点

那么我们所找的合法的答案就应该是:

在起点的右侧的冰锥配对,以及可以绕过来和起点配对的组合

这样就可以用单调栈维护,去重再开一个数组记录栈顶元素个数就行

Noip模拟41 2021.8.16
 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 inline int AE86(){
 5     int x=0,f=1; char ch=getchar();
 6     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
 7     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
 8     return x*f;
 9 }
10 const int NN=1e7+5;
11 int n,a[NN],top,stk[NN],maxn,bin[NN];
12 LL ans;
13 namespace WSN{
14     inline short main(){
15         n=AE86();
16         for(register int i=1;i<=n;++i) a[i+n]=a[i]=AE86();
17         for(register int i=1;i<=n;++i) if(a[maxn]<a[i]) maxn=i;
18         for(register int i=maxn;i<=maxn+n-1;++i){
19             while(top&&stk[top]<a[i]) ++ans,--top;
20             stk[top]>a[i] ? (++ans):(ans+=bin[top]+(a[i]!=a[maxn]));
21             stk[++top]=a[i];
22             bin[top]=(a[i]==stk[top-1]?(bin[top-1]+1):(1));
23         }
24         while(top>2){
25             if(stk[top]==stk[2]) break;
26             ++ans,--top;
27         }
28         printf("%lld\n",ans);
29         return 0;
30     }
31 }
32 signed main(){return WSN::main();}
View Code

 

T2 marshland

一眼网络流,可是忘记了$dinic$,考场上比较傻眼

不过没事,这不是最大流,费用流我还没学过,所以就没什么抱怨的

这种题比较套路的做法是一个偶点旁边有上下左右四个奇点,在奇数行的和偶点的入点连边

偶数行的和偶点的出点连边,最后大概长这样:

Noip模拟41 2021.8.16

 

 

然后跑费用流$EK$板子,稍微魔改一下,跑的过程中记录答案就行

Noip模拟41 2021.8.16
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline int AE86(){
 4     int x=0,f=1; char ch=getchar();
 5     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
 6     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
 7     return x*f;
 8 }
 9 const int NN=1100,inf=2e9,MM=1e6+5;
10 int n,m,k,S,T,g[NN][NN];
11 int maxflow,mincost,ans,sum;
12 int pre[MM],incf[MM],dis[MM];
13 bool vis[MM],jin[NN][NN];
14 struct SNOW{int to,next,flow,val;}; SNOW e[MM<<1]; int head[MM],rp=1;
15 inline void add(int x,int y,int w,int c){
16     e[++rp]=(SNOW){y,head[x],w,c}; head[x]=rp;
17     e[++rp]=(SNOW){x,head[y],0,-c};head[y]=rp;
18 }
19 queue<int> q;
20 inline bool spfa(){
21     memset(dis,-0x3f,sizeof(dis));
22     memset(vis,0,sizeof(vis));
23     dis[S]=0; vis[S]=1; q.push(S); incf[S]=1<<30;
24     while(!q.empty()){
25         int x=q.front(); q.pop(); vis[x]=0;
26         for(register int i=head[x],y;i;i=e[i].next){
27             if(!e[i].flow) continue;
28             if(dis[y=e[i].to]<dis[x]+e[i].val){
29                 dis[y]=dis[x]+e[i].val;    pre[y]=i;
30                 incf[y]=min(incf[x],e[i].flow);
31                 if(!vis[y]) vis[y]=1,q.push(y);
32             }
33         }
34     }
35     if(dis[T]<0) return 0;
36     return 1;
37 }
38 inline void EK(){
39     while(spfa()){
40         int x=T;
41         if(maxflow+incf[T]>m) break;
42         maxflow+=incf[T];
43         mincost=max(mincost,mincost+dis[T]*incf[T]);
44         while(x!=S){
45             int i=pre[x];
46             e[i].flow-=incf[T];
47             e[i^1].flow+=incf[T];
48             x=e[i^1].to;
49         }
50         ans=min(ans,sum-mincost);
51     }
52 }
53 inline int id(int x,int y,int opt){return n*(x-1)+y+opt*n*n;}
54 namespace WSN{
55     inline short main(){
56         n=AE86(); m=AE86(); k=AE86(); S=n*n*2+1; T=S+1;
57         for(register int i=1;i<=n;++i) for(register int j=1;j<=n;++j){
58             g[i][j]=AE86(); sum+=g[i][j];
59             if(!g[i][j])
60                 if(i&1) add(S,id(i,j,0),1,0);
61                 else add(id(i,j,0),T,1,0);
62         }
63         for(register int i=1;i<=k;++i) jin[AE86()][AE86()]=1;
64         for(register int i=1;i<=n;++i) for(register int j=1;j<=n;++j) if(g[i][j]){
65             if(i&1){
66                 if(j-1>0&&!jin[i][j-1]) add(id(i,j-1,0),id(i,j,0),1,0);
67                 if(j+1<=n&&!jin[i][j+1]) add(id(i,j+1,0),id(i,j,0),1,0);
68                 if(i+1<=n&&!jin[i+1][j]) add(id(i,j,1),id(i+1,j,0),1,0);
69                 if(i-1>0&&!jin[i-1][j]) add(id(i,j,1),id(i-1,j,0),1,0);
70             }else{
71                 if(i+1<=n&&!jin[i+1][j]) add(id(i+1,j,0),id(i,j,0),1,0);
72                 if(i-1>0&&!jin[i-1][j]) add(id(i-1,j,0),id(i,j,0),1,0);
73                 if(j-1>0&&!jin[i][j-1]) add(id(i,j,1),id(i,j-1,0),1,0);
74                 if(j+1<=n&&!jin[i][j+1]) add(id(i,j,1),id(i,j+1,0),1,0);
75             }add(id(i,j,0),id(i,j,1),1,g[i][j]);
76         }
77         ans=sum; EK();
78         printf("%d\n",ans);
79         return 0;
80     }
81 }
82 signed main(){return WSN::main();}
View Code

 

T3 party?

考场上做完了预处理的工作,然后就傻眼了,因为T2看出网络流

这题就没有往那里想,网络流可以拿到暴力分其实

先用$bitset$预处理出每一条路径有多少中可能选择的特产,线段树+树剖比较显然

然后就是考虑如何满足题意找到最大合法情况

我们建一个二分图,左部点是人,右部点是特产,每个人分裂成答案个

这样的话,让二分图实现完美匹配即可。

问题转化成要找到一个满足可以二分图完美匹配的最大的$k$

然后引入一个霍尔定理(雾)

一个二分图 $(G)$ 存在完美匹配, 当且仅当 $(X)$ 中的任意 $(k)$ 个点都至少与 $(Y)$ 中的 $(k)$ 个点邻接.

 

左部$c*k$个点只有$c$种邻接关系不同的点,所以$2^c$枚举子集,用$bitset$取并找邻接点个数

则最大的$k$即为邻接点个数和子集个数比值最小值

Noip模拟41 2021.8.16
 1 #include<bits/stdc++.h>
 2 #define bs bitset<1005>
 3 #define lid (id<<1)
 4 #define rid (id<<1|1)
 5 using namespace std;
 6 inline int AE86(){
 7     int x=0,f=1; char ch=getchar();
 8     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
 9     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
10     return x*f;
11 }
12 inline int min(int a,int b){return a<b?a:b;}
13 inline void swap(int &a,int &b){a^=b^=a^=b;}
14 const int NN=3e5+1;
15 bs b[NN];
16 int n,m,q,a[NN],ci[NN],num,ans,c,lca;
17 int dfn[NN],rk[NN],son[NN],fa[NN],siz[NN],dep[NN],top[NN],cnt;
18 struct SNOW{int to,next;};SNOW e[NN<<1]; int head[NN],rp;
19 inline void add(int x,int y){
20     e[++rp]=(SNOW){y,head[x]};head[x]=rp;
21     e[++rp]=(SNOW){x,head[y]};head[y]=rp;
22 }
23 struct SNOWtree{
24     int ll[NN<<2],rr[NN<<2]; bs te[NN<<2];
25     inline void pushup(int id){
26         if(ll[id]==rr[id]) return;
27         te[id]=te[lid]|te[rid];
28     }
29     inline void build(int id,int l,int r){
30         ll[id]=l;rr[id]=r;
31         if(l==r){te[id][a[rk[l]]]=1;return;}
32         int mid=l+r>>1;
33         build(lid,l,mid); build(rid,mid+1,r);
34         pushup(id);
35     }
36     inline bs query(int id,int l,int r){
37         if(l<=ll[id]&&rr[id]<=r) return te[id];
38         int mid=ll[id]+rr[id]>>1; bs ans;
39         if(l<=mid) ans|=query(lid,l,r);
40         if(r>mid) ans|=query(rid,l,r);
41         return ans;
42     }
43 }tr;
44 inline void dfs1(int f,int x){
45     dep[x]=dep[f]+1; siz[x]=1;
46     for(register int i=head[x],y;i;i=e[i].next) if((y=e[i].to)!=f){
47         dfs1(x,y); siz[x]+=siz[y];
48         if(siz[son[x]]<siz[y]) son[x]=y;
49     }
50 }
51 inline void dfs2(int x,int t){
52     top[x]=t; dfn[x]=++cnt; rk[cnt]=x;
53     if(x!=t) b[x]=b[fa[x]]; b[x].set(a[x]);
54     if(son[x]) dfs2(son[x],t);
55     for(register int i=head[x],y;i;i=e[i].next) if((y=e[i].to)!=fa[x]&&y!=son[x]) dfs2(y,y);
56 }
57 inline int LCA(int x,int y){
58     while(top[x]!=top[y]){
59         if(dep[top[x]]<dep[top[y]]) swap(x,y);
60         x=fa[top[x]];
61     }if(dfn[x]>dfn[y]) swap(x,y);
62     return x;
63 }
64 inline bs query(int x,int y){
65     bs ans;
66     while(top[x]!=top[y]){
67         if(dep[top[x]]<dep[top[y]]) swap(x,y);
68         ans|=b[x];
69         x=fa[top[x]];
70     }if(dfn[x]>dfn[y]) swap(x,y);
71     ans|=tr.query(1,dfn[x],dfn[y]);
72     return ans;
73 }
74 namespace WSN{
75     inline short main(){
76         n=AE86();m=AE86();q=AE86(); if(!q) return 0;
77         for(register int i=2;i<=n;++i) fa[i]=AE86(),add(i,fa[i]);
78         for(register int i=1;i<=n;++i) a[i]=AE86();
79         dfs1(0,1);dfs2(1,1);tr.build(1,1,n);
80         while(q--){
81             c=AE86(); bs tmp[6]; ci[1]=AE86(); ci[2]=AE86();
82             ans=0x3fffffff; lca=LCA(ci[1],ci[2]);
83             for(register int i=3;i<=c;++i) ci[i]=AE86(),lca=LCA(lca,ci[i]);
84             for(register int i=1;i<=c;++i) tmp[i]=query(ci[i],lca);
85             for(register int s=1;s<(1<<c);++s){
86                 bs cc;num=0;
87                 for(register int i=0;i<c;++i) if((1<<i)&s) ++num,cc|=tmp[i+1];
88                 ans=min(ans,(int)cc.count()/num);
89             }printf("%d\n",ans*c);
90         }
91         return 0;
92     }
93 }
94 signed main(){return WSN::main();}
View Code

 

T4 半夜

沽沽沽

 

上一篇:【Python】获取翻页之后的各页面中的属性值。


下一篇:CF93D Flags