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 }
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 }
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 }
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 }
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 }
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 }