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
  • 相关阅读:
    easyExcel入门
    UML-从需求到设计--迭代进化
    UML-操作契约总结
    102. Binary Tree Level Order Traversal
    98. Validate Binary Search Tree
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    94. Binary Tree Inorder Traversal
    84. Largest Rectangle in Histogram
    92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/vb4896/p/6414807.html
Copyright © 2011-2022 走看看