打了20分钟的时候突然被叫去干活了。。心急火燎的交了A题。然后在8.50的时候坐下来想B题,最后在回寝室的床上打完了。。
赛后补了C题。
这里只放了前三题的题解,第四题开始不会了。。
A CCA的词典
可以证明,对两个单词进行排序,如果排序以后相同,那么就可以认为两个原单词是一样的。
注意到单词长度<=2。所以我们直接比较两个位置的字母排序,然后哈希就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
int t[100000];
int main()
{
int n;
string s;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s;
int tmp=0;
int a,b;
a=s[0]-'a'+1;
if(s.size()==1)b=0;
else b=s[1]-'a'+1;
if(a>b)swap(a,b);
tmp=a*100+b;
t[tmp]++;
}
int q;
cin>>q;
string c;
while(q--){
cin>>c;
int tmp=0;
int a,b;
a=c[0]-'a'+1;
if(c.size()==1)b=0;
else b=c[1]-'a'+1;
if(a>b)swap(a,b);
tmp=a*100+b;
cout<<t[tmp]<<endl;
}
return 0;
}B CCA的搬运
这题想了挺久的,然后写的时候由于心急一直写错。。
首先题目告诉我们,每次取一个球然后会把他放到最上面。
我们考虑一种比较特殊的情况,每个球都会被取一次。此时我们考虑最后一个球,当他被取的时候,他肯定在最下方。同理,上一个球被取肯定在倒数第二个位置。
那么位置就被固定了。要让消耗最小,我们其实只能按照小球被叫的顺序从上往下放。
那我们其实只要模拟这个过程就好了。由于小球可能会被重复取,我们其实需要知道当前被取小球的上面有哪些小球。发现n,m<=2000。因此我们开个数组每次都暴力的去维护小球的位置。
复杂度就是O(n*m)
代码:
#include<bits/stdc++.h>
using namespace std;
int vis[2003],c[200003];
int main()
{
int n,m;
long long sum=0;
cin>>n>>m;
int a[3000],b[3000];
for(int i=1;i<=n;i++)cin>>a[i];
long long ans=0;
long long tot=0;
for(int i=1;i<=m;i++){
cin>>b[i];
}
for(int i=1;i<=m;i++){
if(!vis[b[i]]){
vis[b[i]]=1;
ans+=sum;
c[++tot]=b[i];
sum+=a[b[i]];
}
else {
int tmp=0,k=tot;
for(int j=tot;j>=1;j--){
if(c[j]==b[i]){
ans+=tmp;
k=j;
break;
}
else tmp+=a[c[j]];
}
for(int j=k;j<=tot-1;j++)c[j]=c[j+1];
c[tot]=b[i];
}
}
cout<<ans<<endl;
}C CCA的子树
这题应该是比较容易想到的。简单的树形dp。
首先Error的情况就是只有一条链的时候。
令dp[i][1/2]表示以点i为根节点的选1/2个子树的最大点权和。
考虑某个结点x,我们可以在dfs中枚举x连出去的边,得到另一个端点y。根据题意我们可以得到转移方程:
dp[x][1]=max(dp[y][1],sum[x])。其中sum[x]为选x点的点权和
dp[x][2]=max(dp[y][2],m1+m2)。其中m1,m2为dp[y][1]中的最大值和次大值。这个m1m2我们可以在计算dp[y][1]的时候进行维护。
代码:
#include<bits/stdc++.h>
using namespace std;
const int inf=1e16;
int n,a[200040],d[200400];
int tot,head[200030];
struct node{
int to,next;
}e[400050];
long long f[200400][3];
void init(){
tot=0;
memset(head,-1,sizeof(head));
for(int i=0;i<200005;i++)f[i][1]=f[i][2]=-inf;
}
void add(int a,int b){
tot++;
e[tot].to=b;
e[tot].next=head[a];
head[a]=tot;
}
long long dfs(int x){
long long m1,m2;
m1=m2=-inf;
long long sum=a[x];
int ff=0;
for(int i=head[x];~i;i=e[i].next){
int y=e[i].to;
ff=1;
sum+=dfs(y);
if(m1<f[y][1])m2=m1,m1=f[y][1];
else if(m2<f[y][1])m2=f[y][1];
f[x][1]=max(f[x][1],m1);
f[x][2]=max(f[x][2],f[y][2]);
f[x][2]=max(f[x][2],m1+m2);
}
f[x][1]=max(f[x][1],sum);
return sum;
}
int main()
{
init();
cin>>n;
int maxi=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v);
d[u]++;
maxi=max(maxi,d[u]);
}
dfs(1);
if(maxi==1)cout<<"Error"<<endl;
else
cout<<f[1][2]<<endl;
return 0;
}
京公网安备 11010502036488号