A CCA的词典
题目描述
给定一个有 n 个单词的词典 。
有 q 次询问,每次询问给定一个单词,询问有多少个单词可以通过交换相邻字母(也可以不交换)变成给定的单词 。
输入描述:
第一行一个整数 n 。
接下来 n 行,每行一个单词 。
第 n+2 行一个整数 q 。
接下来 q 行每行一个单词,表示询问 。
输出描述:
共 q 行,每行一个整数,表示有多少个所求单词 。
示例1
输入
复制
4
aa
bb
ab
ba
2
aa
ba
输出
复制
1
2
备注:
n,q <= 10^4,单词长度 <= 2,单词中的字母全为小写。
属于签到题
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define eps 1e-8
//#define mod 1e9+7
using namespace std;
const int p=1e9+7;
const int M=1e7+5;
const int N=1e4+5;//?????????? 4e8
int n,m;
string s;
map < string , int > mp;
void solve()
{
cin>>n;
while(n--)
{
cin>>s;
mp[s]++;
if(s.size()==2)
{
if(s[0]==s[1]) continue;
char ch=s[0];
s[0]=s[1];
s[1]=ch;
mp[s]++;
}
}
cin>>m;
while(m--)
{
cin>>s;
cout<<mp[s]<<endl;
}
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
solve();
return 0;
}
B CCA的搬运
题目描述
在一个竖直的洞里有 n 个有重量的球,需要进行 m 次操作,每次操作需要将其中一个球拿出来然后放在最上面 。
取出一个小球放在最上面需要消耗的体力为它上面的小球的重量之和 。
现在给定每次操作需要取的小球的编号,要求出一种初始的放球方案使得消耗的总体力最少 。
输入描述:
第一行两个正整数 n 和 m,意义如题所示 。
第二行 n 个正整数,分别表示 n 个球的重量 。
第三行 m 个正整数,分别表示 m 次操作取出小球的编号 。
输出描述:
一个整数表示消耗的总体力的最小值 。
示例1
输入
复制
3 3
1 2 3
3 2 1
输出
复制
8
备注:
n,m <= 2000,1 <= 每个小球的重量 <= 100 。
找了半天规律,结果发现暴力就可以解决,吐了。
属于坑爹题。
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define eps 1e-8
//#define mod 1e9+7
using namespace std;
const int p=1e9+7;
const int M=1e7+5;
const int N=1e4+5;//?????????? 4e8
int n,m,t;
int b[N],pos[N];
int ans;
map < int , int > mp,mp2;
int a[N],v[N];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=m;i++) scanf("%lld",&pos[i]);
for(int i=1;i<=m;i++)
{
b[++t]=pos[i];
while(pos[i]==pos[i+1]&&i+1<=m) i++;
// cout<<i<<endl;
}
// for(int i=1;i<=t;i++) cout<<b[i]<<" ";
// cout<<endl;
for(int i=1;i<=t;i++)
{
mp2.clear();
for(int j=i-1;j>mp[b[i]]&&j;j--)
{
if(mp2[b[j]]) continue;
ans+=a[b[j]];
mp2[b[j]]=1;
}
// cout<<i<<" "<<ans<<endl;
mp[b[i]]=i;
}
cout<<ans<<endl;
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
solve();
return 0;
}
C CCA的子树
题目描述
给定一棵 n 个点的带点权的有根树,根节点为 1 。
要选出两个节点,满足任意一个不是另一个的祖先节点,最大化以两个节点为根的子树的点权和 。
如果选不出两棵合法的子树,则输出“Error”。
输入描述:
第一行一个正整数 n 。
第二行 n 个整数,分别表示 n 个点的点权 。
接下来 n - 1 行,每行两个正整数 u,v 表示 u 和 v 之间有一条连边 。
输出描述:
一个整数,表示最大的点权和
示例1
输入
复制
5
10 -5 5 6 7
1 2
1 3
2 4
2 5
输出
复制
13
备注:
n <= 2×10^5,点权的绝对值 <= 10^9
居然可以一发过,没想到,真是没想到,还担心会超时。
简单来说,就是一道LCA题,要找两个子树根节点,使他们的和最大,且两子树不能再同一颗子树内
但是想的超时的情况是这样的,如图(最后找图的循环)
于是我优化了一下,改变根节点,不过后来证明数据比较水
(不过我还是把优化的代码粘上)
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define eps 1e-8
//#define mod 1e9+7
using namespace std;
const int p=1e9+7;
const int M=1e7+5;
const int N=1e6+5;//?????????? 4e8
int n,t;
struct node
{
int ver,next;
}e[N];
int a[N],b[N],fa[N];
int f[N][64];
int root;
struct aa
{
int val,pos;
}sz[N],d[N];
int tot,head[N],flag;
int dep[N];
void add(int x,int y)
{
e[++tot].ver=y;
e[tot].next=head[x];
head[x]=tot;
}
void addedge(int x,int y)
{
add(x,y);add(y,x);
}
bool cmp(aa x,aa y)
{
return x.val>y.val;
}
void dfs1(int x,int pre)
{
sz[x].val=a[x];
sz[x].pos=x;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(y==pre) continue;
dfs1(y,x);
sz[x].val+=sz[y].val;
}
}
void check(int x,int pre)
{
int fl=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(y==pre) continue;
fl++;
check(y,x);
}
if(fl>=2) flag=1,root=x;
}
void bfs()
{
queue < int > q;
q.push(1);
dep[1]=1;
while(q.size())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(dep[y]) continue;
dep[y]=dep[x]+1;
f[y][0]=x;
for(int j=1;j<=t;j++) f[y][j]=f[f[y][j-1]][j-1];
q.push(y);
}
}
}
int lca(int x,int y)
{
if(dep[x]>dep[y]) swap(x,y);
for(int i=t;i>=0;i--) if(dep[f[y][i]]>=dep[x]) y=f[y][i];
if(x==y) return x;
for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
void solve()
{
cin>>n;
t=(int)log(n)/log(2)+1;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%lld%lld",&x,&y);
addedge(x,y);
}
check(1,1);
// cout<<root<<endl;
if(!flag)
{
puts("Error");
return;
}
bfs();
dfs1(root,root);
for(int i=1;i<=n;i++) d[i]=sz[i];
sort(d+1,d+n+1,cmp);
for(int i=1;i<=n;i++)
{
if(d[i].pos==1) continue;
for(int j=i+1;j<=n;j++)
{
if(d[j].pos==1) continue;
int LCA=lca(d[i].pos,d[j].pos);
if(LCA!=d[i].pos&&LCA!=d[j].pos)
{
cout<<d[i].val+d[j].val<<endl;
// cout<<d[i].pos<<" "<<d[j].pos<<" "<<LCA<<endl;
return;
}
}
}
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
solve();
return 0;
}