Problem A:
题意:给定三个人AB,AC,BC的大小相对关系,输出在中间的那个,保证不存在重复的
思路:比较明显的模拟
char s[3];
cin >> s[0] >> s[1]>>s[2];
if(s[0]=='>'){
if(s[1]=='>'){
if(s[2]=='>'){// >>>
cout <<"B"<<endl;
}
else{//>><
cout << "C"<<endl;
}
}
//><>不存在
else{//><<
cout <<"A"<<endl;
}
}
else{
if(s[1]=='>'){//<>
if(s[2]=='>'){//<>>
cout <<"A"<<endl;
}
}
else{
if(s[2]=='>'){
cout <<"C"<<endl;
}
else{
cout <<"B"<<endl;
}
}
}
Problem B:
题意:给点N个家族和M个查询,每个查询给定一个家族名字和性别,判断是不是这个家族第一次出现性别为男的
思路:对于每个家族记录有没有第一次出现即可
int n , m;cin >> n >> m;
map<int,bool> mp;
while(m--){
int x;char op;
cin >> x >> op;
if(op == 'M'){
if(!mp[x]){
mp[x] = true;
cout <<"Yes\n";
}
else{
cout <<"No\n";
}
}
else cout <<"No\n";
}
problem C:
题意:给定两个无向图,图G为目标图,图H为操作图,你需要进行操作添加或删除边 (次数可以为0),使得两个图同构,每个添加或者删除耗费V(i,j)个价值,输出最小耗费价值。
思路:
首先要了解图的同构:两个图顶点数相同,边数相同,每个点度数相同,邻接关系相同。
观察到数据范围N<=8,因此可以将图的所有可能的顶点排列,计算每种排列的转换成本,并找出最小的成本即可
void dfs(int u){
if(u == n + 1)
{
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(e1[i][j] != e2[num[i]][num[j]]){
ans += w[i][j];
}
}
}
minn = min(minn, ans);
return ;
}
for(int i = 1; i <= n; i++){
if(vis[i]) continue;
vis[i] = 1;
num[u] = i;
dfs(u + 1);
vis[i] = 0;
num[u] = 0;
//枚举
}
}
int32_t main(){
cin >> n;
cin >> m2;
for(int i = 1; i <= m2; i++){
int x, y;
cin >> x >> y;
e2[x][y] = e2[y][x] = 1;
}
cin >> m1;
for(int i = 1; i <= m1; i++){
int x, y;
cin >> x >> y;
e1[x][y] = e1[y][x] = 1;
}
for(int i = 1; i < n; i++) for(int j = i + 1; j <= n; j++) cin >> w[i][j];
dfs(1);
cout << minn << endl;
return 0;
}
problem D:
题意:在一条线上有N个村庄,其中第i个村庄位于X_i处有P_i个村民,有Q个查询,每次给定L,R输出L,R之间(含)村庄的村民总数
| X_i,P_i | <= 1e9 ,N<=2e5
思路:观察到数据很稀疏,可以使用离散化+前缀和,查询的时候使用二分
cin >> n;
VI x;
VI p;
for (int i = 0; i < n; i++) {
int xx;
cin >> xx;
x.push_back(xx);
}
for (int i = 0; i < n; i++) {
int pp;
cin >> pp;
p.push_back(pp);
}
for (int i = 0; i < n; ++i) {
s[i + 1] = s[i] + p[i];
}
cin >> q;
while (q--) {
int L, R;
cin >> L >> R;
VI::iterator itl = lower_bound(x.begin(), x.end(), L);
VI::iterator itr = upper_bound(x.begin(), x.end(), R);
int l = distance(x.begin(), itl);
int r = distance(x.begin(), itr) - 1;
if (l <= r && l < n && r >= 0) {
LL ans = s[r + 1] - s[l];
cout << ans <<endl;
} else {
cout << 0 << endl;
}
}
problem E:
题意:给定一个长度为 n的数组 a,定义函数f(i,j)表示区间 (al,al+1,…ar)中不同值的个数
求:,数据范围2e5
思路:翻译过来就是:求每个子区间内含有的不同数字的个数之和
考虑枚举右端点,记last_i为 i这个数最后出现的位置,每次在右边插入一个数,实时更新对前面最有左端点的影响,可以发现对1-last_i的位置没有影响,而对last_i + 1到当前位置有影响,统计答案并更新last_i即可
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
sum+=i-lst[a[i]];
lst[a[i]]=i;
ans+=sum;
}
cout<<ans;