8.10模拟赛

T1 方案统计

题目大意:

给出一棵n个节点的无根树,其中m个节点是特殊节点,求对于任意0<=i<=m,包含i个特殊节点的联通块个数

思路:

树形dp 

dp i j表示以i为根的子树 包含j个特殊节点的联通块个数

转移就是枚举该节点任意两个子树 dp i j+k  +=  dp to[i] j  *  dp i k  从大到小枚举避免重复计算

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #define MAXN 1100
11 #define ll long long
12 #define inf 2139062143
13 #define MOD 998244353
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 int n,m,g[MAXN],fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
23 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
24 ll sz[MAXN],dp[MAXN][MAXN],ans[MAXN];
25 void dfs(int x,int fa)
26 {
27     sz[x]=g[x],dp[x][sz[x]]=1,ans[sz[x]]++;
28     for(int i=fst[x];i;i=nxt[i])
29         if(to[i]!=fa)
30         {
31             dfs(to[i],x);
32             for(int j=sz[x];j>=g[x];j--)
33                 for(int k=sz[to[i]];k>=0;k--)
34                     (ans[j+k]+=dp[to[i]][k]*dp[x][j]%MOD)%=MOD,(dp[x][j+k]+=dp[to[i]][k]*dp[x][j]%MOD)%=MOD;
35             sz[x]+=sz[to[i]];
36         }
37 }
38 int main()
39 {
40     freopen("tree.in","r",stdin);
41     freopen("tree.out","w",stdout);
42     n=read(),m=read();int a,b;
43     for(int i=1;i<=m;i++) g[read()]=1;
44     for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
45     dfs(1,0);
46     for(int i=0;i<=m;i++) printf("%lld ",ans[i]);
47 }
View Code

T2 机器人装配

题目大意:

有n个机器人和m个配件,每个机器人需要若干个的配件

每个机器人对每个配件都有一定适配度

求每个机器人分配其所需数量的配件,所有机器人对其分配到的配件的适配度之和最大是多少

思路:

建立费用流模型

源点向机器人连流量为所需配件数,费用为0的边

机器人向配件连流量为1,费用为适配度的边

配件向汇点连流量为1,费用为0的边

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #define MAXN 310
11 #define MAXM 30100
12 #define ll long long
13 #define inf 2139062143
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 int n,m,ans;
23 struct ZKW
24 {
25     int fst[MAXN],to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cos[MAXM<<1],cnt;
26     int dis[MAXN],s,t,vis[MAXN];
27     ZKW() {ans=0,cnt=2;}
28     void add(int u,int v,int w,int c) {nxt[cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w,cos[cnt++]=c;}
29     int spfa()
30     {
31         memset(dis,127,sizeof(dis));
32         queue<int> q;
33         dis[t]=0,vis[t]=1;q.push(t);
34         while(!q.empty())
35         {
36             int x=q.front();q.pop();vis[x]=0;
37             for(int i=fst[x];i;i=nxt[i])
38                 if(val[i^1]&&dis[to[i]]>dis[x]-cos[i])
39                 {
40                     dis[to[i]]=dis[x]-cos[i];
41                     if(!vis[to[i]]) {q.push(to[i]);vis[to[i]]=1;}
42                 }
43         }
44         memset(vis,0,sizeof(vis));
45         return dis[s]!=inf;
46     }
47     int dfs(int x,int a)
48     {
49         if(x==t||!a) {ans+=dis[s]*a;return a;}
50         if(vis[x]) return 0;
51         vis[x]=1;int res=0,f;
52         for(int i=fst[x];i&&a;i=nxt[i])
53             if(dis[to[i]]==dis[x]-cos[i]&&(f=dfs(to[i],min(a,val[i]))))
54                 res+=f,val[i]-=f,val[i^1]+=f,a-=f;
55         vis[x]=0;
56         return res;
57     }
58     void solve(){while(spfa()) dfs(s,inf+30);}
59 }Z;
60 int main()
61 {
62     freopen("robot.in","r",stdin);
63     freopen("robot.out","w",stdout);
64     n=read(),m=read();int a,b,c,d;
65     Z.s=n+m+1,Z.t=n+m+2;
66     for(int i=1;i<=n;i++) {c=read();Z.add(Z.s,i,c,0);Z.add(i,Z.s,0,0);}
67     for(int i=1;i<=n;i++)
68         for(int j=1;j<=m;j++) {c=read();Z.add(i,n+j,1,-c);Z.add(n+j,i,0,c);}
69     for(int i=1;i<=m;i++) {Z.add(i+n,Z.t,1,0);Z.add(Z.t,i+n,0,0);}
70     Z.solve();printf("%d",-ans);
71 }
View Code

T3 区间选点

题目大意:

数轴上n个点,坐标分别为x i  选出编号连续的一些点,使得被选出的所有点到某一点的距离和的最小值不超过m ,问最多选出多少点

思路:

首先可以想到滑动窗口来维护这个区间

发现权值线段树可以解决掉区间中位数 再维护一下区间内坐标之和 

用中位数*左边数量-左边坐标和+右边坐标和-中位数*右边数量

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #define MAXN 100100
11 #define MAXX 1001000
12 #define ll long long
13 #define inf 2139062143
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 int n,m,l,ans,g[MAXN],val[MAXX<<2],maxn;
23 ll sum[MAXX<<2];
24 void mdf(int k,int l,int r,int x,int p)
25 {
26     if(l==r) {sum[k]+=p*x,val[k]+=p;return ;}
27     int mid=(l+r)>>1;
28     if(x<=mid) mdf(k<<1,l,mid,x,p);
29     else mdf(k<<1|1,mid+1,r,x,p);
30     sum[k]=sum[k<<1]+sum[k<<1|1],val[k]=val[k<<1]+val[k<<1|1];
31 }
32 ll Ask(int k,int l,int r,int x)
33 {
34     if(l==r) return val[k]*maxn+l;
35     int mid=(l+r)>>1;
36     if(val[k<<1]>=x) return Ask(k<<1,l,mid,x);
37     else return Ask(k<<1|1,mid+1,r,x-val[k<<1]);
38 }
39 ll query(int k,int l,int r,int a,int b)
40 {
41     if(a>b) return 0;
42     if(l==a&&r==b) return sum[k];
43     int mid=(l+r)>>1;
44     if(b<=mid) return query(k<<1,l,mid,a,b);
45     else if(a>mid) return query(k<<1|1,mid+1,r,a,b);
46     else return query(k<<1,l,mid,a,mid)+query(k<<1|1,mid+1,r,mid+1,b);
47 }
48 int lft(int k,int l,int r,int a,int b)
49 {
50     if(a>b) return 0;
51     if(l==a&&r==b) return val[k];
52     int mid=(l+r)>>1;
53     if(b<=mid) return lft(k<<1,l,mid,a,b);
54     else if(a>mid) return lft(k<<1|1,mid+1,r,a,b);
55     else return lft(k<<1,l,mid,a,mid)+lft(k<<1|1,mid+1,r,mid+1,b);
56 }
57 ll calc(int x)
58 {
59     if(x==l) return 0;
60     if(x-l==1) return abs(g[x]-g[l]);
61     ll t=(x-l+1)/2+1,k=Ask(1,1,maxn,t),lv=lft(1,1,maxn,1,k%maxn-1),q= k/maxn+2*lv-x+l-1;k%=maxn;
62     return query(1,1,maxn,k+1,maxn)-query(1,1,maxn,1,k-1)+q*k;
63 }
64 int main()
65 {
66     freopen("choose.in","r",stdin);
67     freopen("choose.out","w",stdout);
68     n=read(),m=read();
69     for(int i=1;i<=n;i++) g[i]=read(),maxn=max(maxn,g[i]);
70     for(int i=l=1;i<=n;i++)
71     {
72         mdf(1,1,maxn,g[i],1);
73         while(calc(i)>m) {mdf(1,1,maxn,g[l],-1);l++;}
74         ans=max(ans,i-l+1);
75     }
76     printf("%d",ans);
77 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9454879.html