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
原文地址:https://www.cnblogs.com/uuzlove/p/11907678.html