zoukankan      html  css  js  c++  java
  • Codeforces Round #398 (Div. 2) BCD

    B:The Queue

    题目大意:你要去办签证,那里上班时间是[s,t), 你知道那一天有n个人会来办签证,他们分别是在时间点ai来的。每个人办业务要花相同的时间x,问你什么时候来 排队等待的时间最少。  (如果你和某个人同时来排队,你会排在他后面)         所有时间为正整数。

    题解:

    首先可以模拟出 每个人的业务什么时候会办好,那么最优解要么是在第一个人来之前的一分钟来,即a1-1,要么是在某个人的业务刚办好的时候来。 分别求出要等待的时间即可。

    注意如果有多个人同时来,那么只能在这些人里的最后的业务办好之后来。

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 #include <queue>
    11 using namespace std;
    12 
    13 #define X first
    14 #define Y second
    15 #define Mod 1000000007
    16 #define N 1000010
    17 #define M 101
    18 
    19 typedef long long ll;
    20 typedef pair<int,int> pii;
    21 
    22 int n;
    23 ll s,t,x,ans1,ans2;
    24 ll v[N];
    25 
    26 int main()
    27 {
    28     //freopen("in.in","r",stdin);
    29     //freopen("out.out","w",stdout);
    30     
    31     scanf("%I64d%I64d%I64d",&s,&t,&x);
    32     scanf("%d",&n);
    33 
    34     for (int i=1;i<=n;i++) scanf("%I64d",&v[i]);
    35     while (n && v[n]+x>t) n--;
    36     if (n==0)
    37     {
    38         printf("%I64d
    ",s);
    39         return 0;
    40     }
    41     
    42     ans1=v[1]-1; ans2=s-ans1;
    43     
    44     ll cur=s; 
    45     for (int i=1;i<=n;i++)
    46     {
    47         if (v[i]<=cur) cur+=x;
    48         else cur=v[i]+x;
    49         if (i<n && v[i]==v[i+1]) continue;
    50         if (i<n)
    51         {
    52             ll tmp=v[i+1]-1,tt=max(0ll,cur-tmp);
    53             if (tt<ans2) ans1=tmp,ans2=tt;
    54         }
    55         //cout<<i<<' '<<cur<<endl;
    56     }
    57     if (cur+x<=t)
    58     {
    59         ans1=cur,ans2=0;
    60     }
    61     printf("%I64d
    ",ans1);
    62     return 0;
    63 }
    View Code

    C:Garland

    题目大意:

    给出一棵树,要求分成3部分,每个部分的点权和相同。

    题解:

    首先所有点的点权之和必须是3的倍数,否则无解。记s[x]为以x为根的子树点权和,tmp=所有点权和/3。假设我们选了u,v这两个点,并且切掉了它们到它们的父节点的边。那么符合要求的只有2种情况:

    1.  s[u]=s[v]=tmp.   lca(u,v)!=u  && lca(u,v)!=v.

    2.  s[u]=tmp*2,s[v]=tmp, lca(u,v)=u.     

    首先做一次dfs求出所有s[x]。

    然后做第二次dfs:对于第2种情况,只要记录从根到当前节点是否存在s[u]=tmp*2的点, 如果存在,且当前节点s[v]=tmp,那么就找到了一种分割方案。

    对于第1种情况, 对于当前节点v, 且s[v]=tmp,  我们需要知道是否存在一个点u,满足s[u]=tmp*2,且u不在 根到v的路径中。   这里用点小技巧, 假设dfs到了v,那么根到v的路径中的点都还在栈里, 所以只要考虑已经不在栈里的点u。  具体实现看代码。

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 #include <queue>
    11 using namespace std;
    12 
    13 #define X first
    14 #define Y second
    15 #define Mod 1000000007
    16 #define N 1000010
    17 #define M 101
    18 
    19 typedef long long ll;
    20 typedef pair<int,int> pii;
    21 
    22 int n,t1,t2,rt,tmp,tt;
    23 int father[N],v[N],s[N];
    24 vector<int> g[N];
    25 
    26 void Dfs(int x)
    27 {
    28     s[x]=v[x];
    29     for (int i=0;i<g[x].size();i++)
    30     {
    31         int y=g[x][i]; if (y==father[x]) continue;
    32         Dfs(y); s[x]+=s[y];
    33     }
    34 }
    35 
    36 void Dfs2(int x,int pre)
    37 {
    38     if (pre && s[x]==tmp) t1=pre,t2=x;
    39     if (tt && s[x]==tmp) t1=tt,t2=x;
    40     for (int i=0;i<g[x].size();i++)
    41     {
    42         int y=g[x][i]; if (y==father[x]) continue;
    43         if (x!=rt && s[x]==tmp*2) Dfs2(y,x);
    44         else Dfs2(y,pre); 
    45     }
    46     if (s[x]==tmp) tt=x;
    47 }
    48 
    49 int main()
    50 {
    51     //freopen("in.in","r",stdin);
    52     //freopen("out.out","w",stdout);
    53     
    54     scanf("%d",&n);  int sum=0;
    55     for (int i=1;i<=n;i++) 
    56     {
    57         scanf("%d%d",&father[i],&v[i]);
    58         if (father[i]) g[father[i]].push_back(i);
    59         else rt=i;
    60         sum+=v[i];
    61     }
    62     if (sum%3){printf("-1
    "); return 0;}
    63     tmp=sum/3;
    64     
    65     Dfs(rt);
    66     Dfs2(rt,0);
    67     if (t1 && t2) printf("%d %d
    ",t1,t2);
    68     else printf("-1
    ");
    69     return 0;
    70 }
    View Code

    D:

    有n瓶牛奶,分别还有ai天过期,每天最多喝k瓶。  超市里有m瓶牛奶,分别还有bi天过期, 问最多能从超市里买多少瓶牛奶,使得买来的牛奶加上本来已有的,都可以在过期之前喝完。

    n<=100w.

    题解:

    显然要先买保质期长的牛奶,所以可以考虑二分答案。 如何判断可行性呢?  根据贪心策略,显然要先喝保质期短的牛奶。所以只要把牛奶按保质期排序就好。这里就涉及到将两个单调的序列合并成一个单调序列的问题。  数据范围100w应该是为了卡掉暴力sort合并的O(nlognlogn)解法.

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 #include <queue>
    11 using namespace std;
    12 
    13 #define X first
    14 #define Y second
    15 #define Mod 1000000007
    16 #define N 1000010
    17 #define M 101
    18 
    19 typedef long long ll;
    20 typedef pair<int,int> pii;
    21 
    22 int n,m,k;
    23 int a[N],q[N<<1];
    24 
    25 struct node
    26 {
    27     int v,id;
    28     bool operator < (const node &t)const
    29     {
    30         return v<t.v;
    31     }
    32 }b[N];
    33 
    34 bool check(int mid)
    35 {
    36     int i=0,j=mid,cnt=0;
    37     while (i<n || j<m)
    38     {
    39         if (i>=n) q[cnt]=b[j].v,j++;
    40         else if (j>=m) q[cnt]=a[i],i++;
    41         else
    42         {
    43             if (a[i]<b[j].v) q[cnt]=a[i],i++;
    44             else q[cnt]=b[j].v,j++;
    45         }
    46         if (cnt/k>q[cnt]) return false;
    47         cnt++;
    48     }
    49     return true;
    50 }
    51 
    52 int main()
    53 {
    54     //freopen("in.in","r",stdin);
    55     //freopen("out.out","w",stdout);
    56     
    57     scanf("%d%d%d",&n,&m,&k);
    58     for (int i=0;i<n;i++) scanf("%d",&a[i]);
    59     for (int i=0;i<m;i++) scanf("%d",&b[i].v),b[i].id=i+1;
    60     sort(a,a+n);sort(b,b+m);
    61     bool flag=true;
    62     for (int i=0;i<n;i++) if (a[i]<i/k) flag=false;
    63     if (!flag){printf("-1
    "); return 0;}
    64     
    65     int l=0,r=m,mid,ans;
    66     while (l<r)
    67     {
    68         mid=(l+r)>>1;
    69         if (check(mid)) r=mid;
    70         else l=mid+1;
    71     }
    72     
    73     ans=m-l;
    74     printf("%d
    ",ans);
    75     for (int i=m-ans;i<m;i++) printf("%d ",b[i].id);
    76     printf("
    ");
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    SI与EMI(一)
    设计上如何避免EMC问题
    EMC与地之重新认识地
    EMC学习之电磁辐射
    围殴拓扑和端接之终结篇
    T型及Fly_by拓扑之应用总结
    拓扑结构介绍及其种类
    [转]Verilog综合时wire和reg如何防止被优化
    Verilog基础知识0(`define、parameter、localparam三者的区别及举例)
    [转]jumbo frame介绍
  • 原文地址:https://www.cnblogs.com/vb4896/p/6414807.html
Copyright © 2011-2022 走看看