目录
A. Extract Numbers
B. Queries about less or equal elements
C. Make Palindrome
E. Lomsat gelral
A. Extract Numbers
题意:太多不想翻译
思路:字符串模拟,我们使用一个临时变量t去储存每个符号直接的字符串,同时需要注意的是,我们对于空字符串也进行处理,然后在输出的时候判断一下即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
const int maxv = 4e6 + 5;
typedef pair<ll, ll> pll;bool check(string s)//检查子段是否合法
{for(int i=0;i<s.size();i++){if(s[0]=='0'&&s.size()!=1){return false;}if(s[i]<'0'||s[i]>'9') return false;}return true;
}void solve()
{string s;cin>>s;s+=";";vector<string> c1,c2;string t;//储存每个符号之间的字符串for(int i=0;i<s.size();i++){if(s[i]==','||s[i]==';'){if(t.empty()) t.push_back('#');if(check(t)){c1.push_back(t);}else{c2.push_back(t);}t="";}else t+=s[i];}if(c1.size()){cout<<"\"";if(c1[0]!="#") cout<<c1[0];for(int i=1;i<c1.size();i++){cout<<",";if(c1[i]!="#") cout<<c1[i];}cout<<"\"";}else{cout<<"-";}cout<<endl;if(c2.size()){cout<<"\"";if(c2[0]!="#") cout<<c2[0];for(int i=1;i<c2.size();i++){cout<<",";if(c2[i]!="#") cout<<c2[i];}cout<<"\"";}else{cout<<"-";}cout<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;//cin >> t;while (t--){solve();}system("pause");return 0;
}
B. Queries about less or equal elements
题意:给你两个整数数组 a和 b。对于第二个数组 bj中的每个元素,你应该找出数组 a中小于或等于数值 bj的元素个数
思路:大水题,Lower bound即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
const int maxv = 4e6 + 5;
typedef pair<ll, ll> pll;void solve()
{int n,m;cin>>n>>m;vector<int> a(n),b(m);for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<m;i++) cin>>b[i];sort(a.begin(),a.end());for(int i=0;i<m;i++){int t=upper_bound(a.begin(),a.end(),b[i])-a.begin()-1;if(t>=0){cout<<t+1<<" ";}else cout<<0<<" ";}cout<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;//cin >> t;while (t--){solve();}system("pause");return 0;
}
C. Make Palindrome
题意:给定一个字符串,你可以将其中任意一个字符替换,代价为1,或是对其进行排列,代价为0,令其变为回文串的代价最小且输出字典序最小的回文串
思路:贪心,用一个桶去统计每个字符的出现次数,我们让每个字符的出现次数为偶数,且让这种情况的代价最小。对字符串按长度为奇偶进行讨论:
1,奇数:这个时候,有一个字符串的出现次数为奇数,因为所有字符的出现次数非奇即偶,所以我们对于所有出现次数为奇数的字符,对其次数减一,并将其放入一个vector中进行存储,最后我们一定可以得到一个长度为奇数的vector,此时的最优解为将其右半部分变为左半部分即可,例如:abcde,我们将其变为abcba,这样我们就只修改了d和e这两个字符,这样的花费一定最小。最后再将vector中的字符添加回桶中。
2,偶数:这个时候,只需要将为奇数的字符放入vector中然后进行变换即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
const int maxv = 4e6 + 5;
typedef pair<ll, ll> pll;void solve()
{string s;cin>>s;map<char,int> mp;for(int i=0;i<s.size();i++){mp[s[i]]++;}int sz=s.size();/*int f=0;for(int i=0;i<sz;i++){if(s[i]!=s[sz-i-1]) f=1;}if(!f){cout<<s<<endl;return ;}*/if(sz%2){vector<char> res;for(auto [x,y]: mp){if(y%2){mp[x]--;res.push_back(x);}}for(int i=0;i<res.size()/2;i++){res[res.size()-1-i]=res[i];}for(auto x: res) mp[x]++;int i=0;vector<char> z(sz);z[sz/2]=res[res.size()/2];//长度为奇数的情况,最中间的字符直接赋值for(auto [x,y]: mp){//map的key本身有序,所以能直接构造if(y>0){y/=2;for(;y>0;y--){z[i]=z[sz-i-1]=x;i++;}}}for(auto x: z) cout<<x;cout<<endl;}else{vector<char> res;for(auto [x,y]: mp){if(y%2){mp[x]--;res.push_back(x);}}for(int i=0;i<res.size()/2;i++){res[res.size()-1-i]=res[i];}for(auto x: res) mp[x]++;int i=0;vector<char> z(sz);for(auto [x,y]: mp){if(y>0){y/=2;for(;y>0;y--){z[i]=z[sz-i-1]=x;i++;}}}for(auto x: z) cout<<x;cout<<endl;}
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t = 1;//cin >> t;while (t--){solve();}system("pause");return 0;
}
E. Lomsat gelral
题意:给定一颗树,求每个子树中颜色出现次数最多的颜色编号之和。
思路:裸的树上启发式合并。
树上启发式合并:可以高效的用于统计子树信息(不带修改的那种),时间复杂度为nlogn,极为优秀。
基本操作:两遍dfs:
第一遍dfs处理所有节点的相关信息,dfs序,轻儿子和重儿子等。
第二边dfs:
1,先处理所有轻儿子节点,计算但不保留其对于答案的贡献
2,处理所有重儿子节点,保留其对答案的贡献
3,将轻儿子合并进重儿子,计算其对于答案的贡献
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long ll ;
const int maxv=4e6+5;
typedef pair<ll,ll> pll;int l[N],r[N],id[N],sz[N],hs[N],tot;
vector<int> e[N];
int c[N],cnt[N];
ll maxcnt,sumcnt;
ll ans[N];
void dfs1(int u,int f)
{l[u]=++tot;id[tot]=u;sz[u]=1;hs[u]=-1;for(auto v: e[u]){if(v==f) continue;dfs1(v,u);sz[u]+=sz[v];if(hs[u]==-1||sz[v]>sz[hs[u]]) hs[u]=v;}r[u]=tot;
}void add(int x)
{x=c[x];cnt[x]++;if(cnt[x]>maxcnt) maxcnt=cnt[x],sumcnt=0;if(cnt[x]==maxcnt) sumcnt+=x;
}
void del(int x)
{x=c[x];cnt[x]--;
}void dfs2(int u,int f,bool keep)
{for(auto v: e[u]) {if(v!=f&&v!=hs[u]) dfs2(v,u,false);}if(hs[u]!=-1) dfs2(hs[u],u,true);for(auto v: e[u]){if(v!=f&&v!=hs[u]){for(int x=l[v];x<=r[v];x++ ) add(id[x]);}}add(u);ans[u]=sumcnt;if(!keep){for(int x=l[u];x<=r[u];x++) del(id[x]);sumcnt=0,maxcnt=0;}
}void solve()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>c[i];}for(int i=1;i<=n-1;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}dfs1(1,0);dfs2(1,0,false);for(int i=1;i<=n;i++){cout<<ans[i]<<" ";}cout<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();}system("pause");return 0;
}