zoukankan      html  css  js  c++  java
  • codeforces #600 (div 2) 做题记录

    A.

    两个数组作差判一判就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 100005
     3 using namespace std;
     4 int T,n;
     5 int a[maxn],b[maxn];
     6 int main()
     7 {
     8     scanf("%d",&T);
     9     while(T--)
    10     {
    11         scanf("%d",&n);
    12         for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    13         for(int i=1;i<=n;++i)scanf("%d",&b[i]);
    14         for(int i=1;i<=n;++i)a[i]-=b[i];
    15         bool yes=1;
    16         for(int i=1;i<=n;++i)if(a[i]>0)yes=0;
    17         int cnt=0;
    18         for(int i=1;i<=n;++i)
    19         {
    20             if(a[i]!=0&&a[i-1]==0)cnt++;
    21             if(a[i]!=0&&a[i-1]!=0&&a[i]!=a[i-1])yes=0;
    22         }
    23         if(yes&&cnt<=1)puts("YES");
    24         else puts("NO");
    25     }
    26 }
    View Code

    B.

    用一个set维护已经出现的正的,一个set维护当天用过的(出现一正一负的)

    然后各种边界判一判

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 set<int> s,used;
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     bool yes=1;
     9     vector<int> Ans;Ans.clear();
    10     Ans.push_back(0);
    11     for(int i=1;i<=n;++i)
    12     {
    13         int x;
    14         scanf("%d",&x);
    15         if(x<0)
    16         {
    17             if(!s.count(-x)){yes=0;break;}
    18             s.erase(-x),used.insert(-x);
    19         }
    20         else
    21         {
    22             if(s.count(x)){yes=0;break;}
    23             s.insert(x);
    24         }
    25         if(s.count(abs(x))&&used.count(abs(x)))yes=0;
    26         if(s.empty())Ans.push_back(i),used.clear();
    27     }
    28     if(!s.empty())yes=0; 
    29     if(!yes)
    30     {
    31         puts("-1");
    32         return 0;
    33     }
    34     printf("%d
    ",Ans.size()-1);
    35     for(int i=1;i<Ans.size();++i)printf("%d ",Ans[i]-Ans[i-1]);
    36 }
    View Code

    C.

    考虑贪心,一定是从小朝大选

    然后考虑把哪些放在靠前的天数,一定是较小的那些

    然后在( mod m)意义下维护一下就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 1000005
     3 #define ll long long
     4 using namespace std;
     5 int n,m;
     6 ll a[maxn],s[maxn];
     7 int main()
     8 {
     9     scanf("%d%d",&n,&m);
    10     for(int i=1;i<=n;++i)scanf("%I64d",&a[i]);
    11     sort(a+1,a+n+1);
    12     ll ans=0;
    13     for(int i=1;i<=n;++i)
    14     {
    15         ans+=s[i%m];
    16         s[i%m]+=a[i];
    17         ans+=a[i];
    18         printf("%I64d ",ans);
    19     }
    20 }
    View Code

    D.

    考虑一定是连续的一段编号连通

    那么我们从左往右扫,并用一个并查集维护每个连通块里编号最大的点

    然后剩下这段的点都接上去就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 200005
     3 using namespace std;
     4 int n,m;
     5 int fa[maxn],sz[maxn],mx[maxn];
     6 int find(int x)
     7 {
     8     while(x!=fa[x])x=fa[x];
     9     return x;
    10 }
    11 void merge(int u,int v)
    12 {
    13     if(find(u)==find(v))return;
    14     int fu=find(u),fv=find(v);
    15     if(sz[fu]<sz[fv])fa[fu]=fv,mx[fv]=max(mx[fv],mx[fu]),sz[fv]+=sz[fu];
    16     else fa[fv]=fu,mx[fu]=max(mx[fu],mx[fv]),sz[fu]+=sz[fv];
    17 }
    18 int main()
    19 {
    20     scanf("%d%d",&n,&m);
    21     for(int i=1;i<=n;++i)fa[i]=i,sz[i]=1,mx[i]=i;
    22     for(int i=1;i<=m;++i)
    23     {
    24         int u,v;
    25         scanf("%d%d",&u,&v);
    26         merge(u,v);
    27     }
    28     int ans=0;
    29     for(int l=1;l<=n;++l)
    30     {
    31         for(int r=l+1;r<mx[find(l)];++r)
    32         {
    33             if(find(l)!=find(r))ans++,merge(l,r);
    34         }
    35         l=mx[find(l)];
    36     }
    37     cout<<ans<<endl;
    38 }
    View Code

    E.

    考虑DP

    (dp[i][j])表示第(i)个位置被(j)号区间覆盖

    然后考虑转移:

    1.延续这个区间:如果在这个区间内,那么直接延伸,否则用1费延伸

    2.更新对称位置:这个点已经被覆盖了,那么到对称位置肯定也一直被覆盖,转移一下取个(min)

    2.换一个区间:枚举另外一个区间,用另外一个区间,加上花费就行了

     1 #include<bits/stdc++.h>
     2 #define maxn 85
     3 #define maxm 100005
     4 using namespace std;
     5 int n,m;
     6 int X[maxn],S[maxn];
     7 int dp[maxm][maxn];
     8 int main()
     9 {
    10     scanf("%d%d",&n,&m);
    11     for(int i=1;i<=n;++i)scanf("%d%d",&X[i],&S[i]);
    12     for(int i=1;i<=n;++i)dp[1][i]=max(0,X[i]-S[i]-1);
    13     for(int i=2;i<=m;++i)
    14         for(int j=1;j<=n;++j)dp[i][j]=1000000000;
    15     for(int i=1;i<m;++i)
    16     {
    17         for(int j=1;j<=n;++j)
    18         {
    19             if(i+1<=X[j]+S[j])dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
    20             else dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);
    21             if(i<=X[j])dp[min(2*X[j]-i,m)][j]=min(dp[min(2*X[j]-i,m)][j],dp[i][j]);
    22             for(int k=1;k<=n;++k)if(k!=j&&i<=X[k])
    23             {
    24                 if(X[k]-S[k]<=i)dp[i+1][k]=min(dp[i+1][k],dp[i][j]);
    25                 else dp[i+1][k]=min(dp[i+1][k],dp[i][j]+X[k]-S[k]-(i+1));
    26             }
    27         }
    28     }
    29     int ans=1000000000;
    30     for(int i=1;i<=n;++i)ans=min(ans,dp[m][i]);
    31     cout<<ans<<endl;
    32 }
    View Code

    F.

    首先考虑一个事实:我们一条路径一定可以写成(S->k_1->k_2->……->k_x->T)的形式,其中k_i为关键点

    其中关键点之间走的路径一定是最短路

    那么我们的(c)大于等于路径上的最大权

    然后考虑(c)要最小,那么就要找一个路径最大权最小

    我们现在来考虑原图上的一条路径,假设和点(x)最近的关键点为(x'),从(x')到(x)的距离为(d_x)

    那么我们就是从(S)走过一条路径到(T)

    我们走每条边((u,v))的时候,他一定是从(u'->u->v->v')

    而且我们可以证明,他一定会回到v'

    如果再走另一条边,那么证明(c-d_u-w>c-d_v)

    那么就是(d_v>d_u+w)

    这与最近点矛盾

    那么我们就证明了他一定是从u'到u到v回到v',再从v'开始走

    那么我们每个非关键点代表到他最近的那个关键点,把边权改为(d_u+d_v+w)

    然后就是两点之间路径最大权最小

    这个可以求个MST然后树上倍增来做掉

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 #define maxn 600005
      4 using namespace std;
      5 int n,m,k,q;
      6 struct Edg
      7 {
      8     int u,v;
      9     ll w;
     10 }e[maxn];
     11 bool operator < (Edg A,Edg B){return A.w<B.w;}
     12 int fa[maxn];
     13 int find(int x)
     14 {
     15     if(fa[x]==x)return x;
     16     return fa[x]=find(fa[x]);
     17 }
     18 namespace SSSP
     19 {
     20     vector< pair<ll,int> > g[maxn];
     21     void addedge(int u,int v,ll w)
     22     {
     23         g[u].push_back(make_pair(w,v));
     24         g[v].push_back(make_pair(w,u));
     25     }
     26     priority_queue< pair<ll,int> > q;
     27     ll dis[maxn];
     28     bool used[maxn];
     29     void dijkstra()
     30     {
     31         for(int i=1;i<=n;++i)dis[i]=(ll)1e15;
     32         memset(used,0,sizeof(used));
     33         for(int i=1;i<=k;++i)q.push(make_pair(0,i)),dis[i]=0;
     34         while(!q.empty())
     35         {
     36             int u=q.top().second;q.pop();
     37             if(used[u])continue;
     38             used[u]=1;
     39             for(auto x:g[u])
     40             {
     41                 int v=x.second;ll w=x.first;
     42                 if(dis[v]>dis[u]+w)
     43                 {
     44                     dis[v]=dis[u]+w;
     45                     q.push(make_pair(-dis[v],v)); 
     46                 }
     47             }
     48         }
     49     }
     50 }
     51 namespace Tree
     52 {
     53     vector< pair<ll,int> > g[maxn];
     54     void addedge(int u,int v,ll w)
     55     {
     56         g[u].push_back(make_pair(w,v));
     57         g[v].push_back(make_pair(w,u));
     58     }
     59     int d[maxn],anc[maxn][20];
     60     ll maxv[maxn][20];
     61     void dfs(int u,int f)
     62     {
     63         for(auto x:g[u])
     64         {
     65             int v=x.second;ll w=x.first;
     66             if(v==f)continue;
     67             d[v]=d[u]+1,anc[v][0]=u,maxv[v][0]=w;
     68             dfs(v,u);
     69         }
     70     }
     71     void init()
     72     {
     73         for(int j=1;j<=18;++j)
     74             for(int i=1;i<=n;++i)
     75             {
     76                 anc[i][j]=anc[anc[i][j-1]][j-1];
     77                 maxv[i][j]=max(maxv[i][j-1],maxv[anc[i][j-1]][j-1]);
     78             }
     79     }
     80     ll query(int u,int v)
     81     {
     82         ll ans=0;
     83         if(d[u]<d[v])swap(u,v);
     84         for(int i=18;i>=0;--i)if(d[anc[u][i]]>=d[v])
     85         {
     86             ans=max(ans,maxv[u][i]);
     87             u=anc[u][i];
     88         }
     89         if(u==v)return ans;
     90         for(int i=18;i>=0;--i)if(anc[u][i]!=anc[v][i])
     91         {
     92             ans=max(ans,maxv[u][i]);
     93             ans=max(ans,maxv[v][i]);
     94             u=anc[u][i],v=anc[v][i];
     95         }
     96         ans=max(ans,max(maxv[u][0],maxv[v][0]));
     97         return ans;
     98     }
     99 }
    100 int main()
    101 {
    102     scanf("%d%d%d%d",&n,&m,&k,&q);
    103     for(int i=1;i<=m;++i)
    104     {
    105         scanf("%d%d%I64d",&e[i].u,&e[i].v,&e[i].w);
    106         SSSP::addedge(e[i].u,e[i].v,e[i].w);
    107     }
    108     SSSP::dijkstra();
    109     for(int i=1;i<=m;++i)e[i].w+=SSSP::dis[e[i].u]+SSSP::dis[e[i].v];
    110     sort(e+1,e+m+1);
    111     for(int i=1;i<=n;++i)fa[i]=i;
    112     for(int i=1;i<=m;++i)
    113     {
    114         int u=find(e[i].u),v=find(e[i].v);
    115         if(u==v)continue;
    116         Tree::addedge(e[i].u,e[i].v,e[i].w);
    117         fa[u]=v;
    118     }
    119     Tree::dfs(1,0);
    120     Tree::init();
    121     while(q--)
    122     {
    123         int u,v;
    124         scanf("%d%d",&u,&v);
    125         printf("%I64d
    ",Tree::query(u,v));
    126     }
    127 }
    View Code
  • 相关阅读:
    JavaScript技巧大全
    rs.open sql,conn 与conn.execute(sql)的区别
    ASP.NET中常用的优化性能的方法(1)
    JavaScript实现图片的不间断连续滚动
    Windows下安装和配置netbeans以使用C/C++全过程
    hdu Hat's Fibonacci
    hdu Big Number
    hdu Buy the Ticket
    acm steps chapter3总结
    如何从U盘引导安装win7/xp
  • 原文地址:https://www.cnblogs.com/uuzlove/p/11907678.html
Copyright © 2011-2022 走看看