AtCoder Grand Contest 011(AGC011) A~C题解
A
贪心,每一个巴士都尽可能安排在前面。
时间复杂度 O ( n ∗ log 2 ( n ) ) O(n*\log_2(n)) O(n∗log2(n))
/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int n;
int c,k,t[100000+20];
int main(){
fastio;
R(n);
R2(c,k);
rb(i,1,n){
R(t[i]);
}
sort(t+1,t+1+n);
int l=1;
int rest=0;
rb(i,1,n){
if(t[i]-t[l]>k||i-l+1>c){
l=i;
rest++;
}
}
rest++;
cout<<rest<<endl;
return 0;
}
B
若所有的巴士升序排序,那么最后剩下的颜色可以是它的后缀之一。
如果检验 i i i号位置的颜色是否可以留下,我们可以从小往大合并。这样肯定是一段一段的,其中最后一段的长度就是答案。
时间复杂度 O ( n ) O(n) O(n)
/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int n;
int a[100000+20];
int main(){
fastio;
R(n);
rb(i,1,n) R(a[i]);
sort(a+1,a+1+n);
int las=0;
LL sum=0;
while(1){
int index=las+1;
sum+=a[las+1];
while(index!=n&&sum*2>=a[index+1]){
index++;
sum+=a[index];
}
if(index==n){
cout<<n-las<<endl;break;
}
las=index;
}
return 0;
}
C
我们可以给每一个联通块打上一个标记,我们不妨设它是这个联通快内最小的点 ( a , b ) (a,b) (a,b)。
问题转换成:
如果一个点 ( a , b ) (a,b) (a,b)不能连到更小的点 ( a ′ , b ′ ) (a\prime,b\prime) (a′,b′)的化, a n s + + ans++ ans++
那怎么判断一个点 ( a , b ) (a,b) (a,b)是否可以连到更小的点呢?
如果 a a a可以到达的点中,最小值 < a <a <a则 ( a , b ) (a,b) (a,b)可以到达更小的 ( a ′ , b ′ ) (a\prime,b\prime) (a′,b′)其中 a > a ′ a>a\prime a>a′
如果不可以,那么如果 a = a ′ a=a\prime a=a′时, ∀ b ′ ≥ b \forall b\prime\geq b ∀b′≥b,则 ( a , b ) (a,b) (a,b)不能到达更小的点。
假设从 a a a走奇数步可以到达 a a a,则 b b b走奇数步到达的 b ′ b\prime b′中的最小值要 ≥ b \geq b ≥b。
对于偶数也一样。
每一个点经过奇数步/偶数步到达的点的最小值可以用“最短路dp算出”
然后再判断一下没有与别的连边的就行了。
时间复杂度 O ( E ∗ log 2 ( E ) ) O(E*\log_2(E)) O(E∗log2(E)),但是用 0 − 1 b f s 0-1bfs 0−1bfs的思想可以优化到 O ( E ) O(E) O(E)
/*
{By GWj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=100000+20;
int dp[MAXN][2];
vector<int> g[MAXN];
int n,m;
int save=0;
int main(){
fastio;
R2(n,m);
rb(i,1,m){
int u,v;
R2(u,v);
g[u].PB(v);
g[v].PB(u);
}
set<pair<int,pair<int,bool> >> heap;
memset(dp,63,sizeof(dp));
rb(i,1,n)
dp[i][0]=i,heap.insert(II(i,II(i,0)));
while(!heap.empty()){
pair<int,pair<int,bool> > now=*heap.begin();
heap.erase(heap.begin());
int i,j,val;
i=now.SEC.FIR;
j=now.SEC.SEC;
val=now.FIR;
if(dp[i][j]!=val) continue;
for(auto it:g[i]){
if(dp[it][j^1]>dp[i][j]){
dp[it][j^1]=dp[i][j];
heap.insert(II(val,II(it,j^1)));
}
}
}
int N=0;
rb(i,1,n){
N+=g[i].empty();
}
int save1=0,save0=0,save3=0;
rb(i,1,n){
if(g[i].size()){
if(dp[i][0]==i){
save3+=dp[i][1]>=i;
save0++;
}
if(dp[i][1]>=i){
save1++;
}
}
}
LL rest=1ll*N*n*2-1ll*N*N;
rb(i,1,n){
if(g[i].size())
if(min(dp[i][0],dp[i][1])==i){
if(dp[i][0]==i&&dp[i][1]==i){
rest+=save3;
}
else{
rest+=save0;
}
}
}
cout<<rest<<endl;
return 0;
}