A
對數組排序,如果存在相鄰兩項爲1,則最少可以分成兩組,否則分成1組。
#include<bits/stdc++.h>
using namespace std;
int a[200];
int main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
int res=0;
for(int i=2;i<=n;i++){
if(a[i]-a[i-1]==1) res++;
}
if(res) cout<<2<<endl;
else cout<<1<<endl;
}
return 0;
}
B1&B2
整個問題可以轉化爲一個圖求各個環的大小的問題,由於每個點只會在一個環中出現,考慮 或 求環即可。
時間複雜度。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
vector<int> G[N];
bool is_instack[N];
int dfn[N],low[N],siz[N],color[N],a[N];
stack<int> sta;
int n,m,idx,scc;
void init(int n){
idx=scc=0;
for(int i=0;i<=n;i++) dfn[i]=low[i]=is_instack[i]=color[i]=siz[i]=0;
while(!sta.empty()) sta.pop();
for(int i=0;i<=n;i++) G[i].clear();
}
void Tarjan(int u){
low[u]=dfn[u]=++idx;
is_instack[u]=1;sta.push(u);
for(int v:G[u]){
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
scc++;
while(1){
int temp=sta.top();
color[temp]=scc;
siz[scc]++;
is_instack[temp]=0;
sta.pop();
if(temp==u) break;
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init(n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
G[i].push_back(a[i]);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) Tarjan(i);
}
for(int i=1;i<=n;i++){
printf("%d ",siz[color[i]]);
}
puts("");
}
return 0;
}
C1&C2
的本質即爲三進制下各位都不是的數字,因此對於,在三進制下找到最左邊的然後變爲,後面的全部變爲即可。複雜度。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string change(ll x){
if(x==0) return "0";
string res="";
while(x){
res+=char(x%3+'0');
x/=3;
}
res+="0";
reverse(res.begin(),res.end());
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--){
ll n;
cin>>n;
string now=change(n);
// cout<<n<<" base3 "<<now<<endl;
bool f=0;
for(char v:now){
if(v=='2') f=1;
}
if(!f){
cout<<n<<endl;continue;
}
int len=(int)now.length();
ll ans=0;
int id;
for(int i=0;i<len;i++){//找到第一個2
if(now[i]=='2'){
id=i;break;
}
}
int id2;
for(int i=id;i>=0;i--){//找到離2最近的0
if(now[i]=='0'){
id2=i;
now[i]='1';break;
}
}
for(int i=id2+1;i<len;i++) now[i]='0';//後面全爲0
for(char c:now){
ans=ans*3+(c-'0');
}
cout<<ans<<endl;
}
return 0;
}
D1&D2
考慮貪心:每次選取最左邊的被線段覆蓋超過次的點,按照右端點從大到小刪除覆蓋該點的線段,依次模擬即可。
可以考慮使用,時間複雜度。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
vector<pair<int,int> > seg[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,k,l,r;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>l>>r;
seg[l].push_back({r,i});
}
vector<int> del;
set<pair<int,int> > q;
for(int i=0;i<=2e5+1;i++){
for(auto v:seg[i]){
q.insert(v);
}
while(q.size()>k){
del.push_back(q.rbegin()->second);
q.erase(*q.rbegin());
}
while(!q.empty()&&q.begin()->first<=i) q.erase(*q.begin());//去掉沒有覆蓋i+1的
}
cout<<(int)del.size()<<endl;
for(int v:del) cout<<v<<' ';
cout<<endl;
}
E
簡單,和代表到第層最後使用電梯還是樓梯的最小值,直接轉移即可,時間複雜度。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+7;
ll dp[N][2];
ll a[N],b[N],ans[N];
int main(){
int n,c;
cin>>n>>c;
for(int i=2;i<=n;i++) cin>>a[i];//st
for(int i=2;i<=n;i++) cin>>b[i];//el
memset(dp,0x3f,sizeof(dp));
dp[1][0]=0;
dp[1][1]=c;
cout<<0;
for(int i=2;i<=n;i++){
dp[i][0]=min(dp[i-1][0]+a[i],dp[i-1][1]+a[i]);//st
dp[i][1]=min(dp[i-1][0]+b[i]+c,dp[i-1][1]+b[i]);//el
ans[i]=min(dp[i][0],dp[i][1]);
}
for(int i=2;i<=n;i++) cout<<' '<<ans[i];
cout<<endl;
return 0;
}