1001.Theramore
易知,字符串的奇偶项之间不会互换,只需要奇偶分别排序即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
vector<int>odd,even;
string s;
cin>>s;
for( int i=0;i<s.size();i++){
if(i%2) odd.push_back(s[i]-'0');
else even.push_back(s[i]-'0');
}
sort(odd.begin(),odd.end());
sort(even.begin(),even.end());
for( int i=0;i<s.size();i++){
if(i%2){
cout<<odd[i/2];
}
else cout<<even[i/2];
}
cout<<"\n";
}
signed main(){
int t;
cin>>t;
while(t--){
solve();
}
}
1007.Darnassus
kruskal最小生成树算法
若使用暴力法,则共有n^2条边,时间复杂度过高。
可以考虑通过边的取值范围来限制问题的规模,由于每条边的长度至多为
n-1
,因此|i-j|
和|pi-pj|
至少有一个小于sqrt(n-1)
这样可以将问题的规模降至n*sqrt(n)
再使用桶排序对所有的边进行排序,最后使用kruskal算法得出答案。
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
struct dsu
{
const int n;
vector<int>a;
dsu( int n):n(n+1),a(n+1){
for( int i=0;i<n+1;i++) a[i]=i;
}
//y向x合并
void unite(int x, int y) {
a[find(y)] = find(x);
}
int find(int u) {
return a[u] == u ? a[u] : a[u] = find(a[u]);
}
};
ll solve(){
int n;
cin>>n;
vector<int>v1(n+1),v2(n+1);
vector<vector<pair<int,int>>>val(n);
dsu d(n+1);
int cnt=0;
for( int i=1;i<=n;i++){
cin>>v1[i];
}
for( int i=1;i<=n;i++){
v2[v1[i]]=i;
}
for( int i=1;i<=n;i++){
for( int j=i+1;j<=n;j++){
if(1ll*abs(i-j)*abs(i-j)>=n) break;
int x=abs(i-j)*abs(v1[i]-v1[j]);
if(x<n)
val[x].push_back({i,j});
x=abs(i-j)*abs(v2[i]-v2[j]);
if(x<n)
val[x].push_back({v2[i],v2[j]});
}
}
ll ans=0;
for( int i=1;i<n;i++){
for( auto it:val[i]){
int x=it.first,y=it.second;
if(d.find(x)!=d.find(y)){
ans+=i;
d.unite(x,y);
}
}
}
return ans;
}
signed main(){
std::ios::sync_with_stdio(false);//消除输入输出缓存
std::cin.tie(0);//解除cin与cout的绑定,加快速率。
int t;
cin>>t;
while(t--){
cout<<solve()<<"\n";
}
// system("pause");
}
1008.Orgrimmar
求一棵树的最大分离集的大小,只需要分状态dp即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll solve(){
int n;
cin>>n;
vector<vector<int>>g(n+1);
for( int i=0;i<n-1;i++){
int x,y;
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
vector<array<int,3>>dp(n+1);
auto dfs=[&](auto self, int rt,int fa)->void{
dp[rt][0]=dp[rt][1]=1;
int x=1e9,y=0;
int sum=0;
for( auto it:g[rt]){
if(it==fa) continue;
else {
self(self,it,rt);
dp[rt][0]+=dp[it][2];
x=min(x,dp[it][2]-dp[it][0]);
sum+=dp[it][2];
dp[rt][2]+=max({dp[it][0],dp[it][1],dp[it][2]});
}
}
dp[rt][1]+=max({sum,sum-x});
};
dfs(dfs,1,0);
return max({dp[1][0],dp[1][1],dp[1][2]});
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int size(512<<20); // 512M
__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
// YOUR CODE
int t;
cin>>t;
while(t--){
cout<<solve()<<"\n";
}
exit(0);
}
1011.Stormwind
将一个矩形切割成若干个矩形,只需枚举长的方向上被切的数量,再计算宽上对应的被切割成的数量。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll solve(){
ll n,m,k;
cin>>n>>m>>k;
ll ans=0;
for( ll i=1;i<=n;i++){
ll area=(n/i)*m;
if(area<k) continue;
ll j=min(m,area/k);
while(j!=0&&(n/i)*(m/j)<k){
j--;
}
if(j<=0) continue;
ans=max(ans,i+j-2);
}
return ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
cout<<solve()<<"\n";
}
system("pause");
}