zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Java数据结构和算法总结-数组、二分查找
    Android开发必知--使用View.setId的正确姿势
    Fiddler基本用法以及如何对手机抓包
    Android学习笔记(十四)方便实用的首选项-PreferenceActivity
    Android学习笔记(十三)SharedPreference必须掌握的基础
    设计模式之单例模式
    关于如何控制一个页面的Ajax读数据只读一次的简单解决办法!
    ASP.NET MVC 表单提交多层子级实体集合数据到控制器中
    使用Bootstrap的popover标签中嵌入插件,并且为插件注册事件实现Ajax与后台交互
    关于.Net使用企业库访问MySql数据库
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9454879.html
Copyright © 2011-2022 走看看