A. Twin Permutations
题意:
给一个permutation类数组(即长度为n的数组,必须1~n都存在) a ,让找到一个相同长度的 数组 b,使得 a i + b i ≤ a i + 1 + b i + 1 a_i+b_i \leq a_{i+1}+b_{i+1} ai+bi≤ai+1+bi+1
思路:
和等差数列一样 a 1 + a n = a 2 + a n − 1 a_1+a_n=a_2+a_{n-1} a1+an=a2+an−1, 即每个数都有一个配对的数可以使得他们加起来相等;
代码
void solve()
{
cin>>n;
int x;
for(int i=1;i<=n;i++) {cin>>x;cout<<n+1-x<<" "};
cout<<endl;
}
B. Array merging
题意
两个数组,找合在一起后最长的相同元素的子串。合的过程是从 a,b数组一个一个拿下来;
思路:
两个数组中相同的元素的长度加起来求max
代码:
int n,m,k,_;
int a[N*2],b[N*2];
int cnt1[N*2],cnt2[N*2];
map<int,int>mp;
void solve()
{
cin>>n;
for(int i=1;i<=n*2;i++)
cnt1[i]=cnt2[i]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=1;i<=n;)
{
int j=i+1;
while(a[j]==a[i]&&j<=n) j++;
cnt1[a[i]]=max(cnt1[a[i]],j-i);
i=j;
}
int mx=0;
for(int i=1;i<=n;)
{
int j=i+1;
while(b[j]==b[i]&&j<=n) j++;
cnt2[b[i]]=max(cnt2[b[i]],j-i);
i=j;
}
for(int i=1;i<=2*n;i++)
mx=max(cnt1[i]+cnt2[i],mx);
cout<<mx<<endl;
}
C. Copil Copac Draws Trees
思路:
记一下边的序号再dfs
代码
vector<int>e[N];
bool vis[N];
map<PII,int>mp;
int dfs(int p,int s)
{
int ans=0;
for(auto u:e[s])
ans=max(ans,dfs(s,u)+(mp[{p,s}]<mp[{s,u}]));
return ans;
}
void solve()
{
cin>>n;
memset(vis,0,sizeof vis);
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
mp[{u,v}]=i;
mp[{v,u}]=i;
}
int ans=0;
for(auto p:e[1]) ans=max(ans,dfs(1,p));
cout<<ans<<endl;
}
D. The BOSS Can Count Pairs
题意:
给长度为n、范围为1~n的两个数组a、b, 求有多少组 a i ∗ a j = b i + b j a_i * a_j = b_i + b_j ai∗aj=bi+bj , 1 ≤ n ≤ 2 × 1 0 5 1 \leq n \leq 2 \times 10^5 1≤n≤2×105,
思路(值域):
1.等于左右的值域相同,右边的值域为2~2n,左边为1 ~ n 2 n^2 n2, 故最终值域应该为 2~2n 。
-
假设 a i ≤ a j a_i \leq a_j ai≤aj 那么 a i × a i ≤ 2 × n a_i \times a_i\leq 2\times n ai×ai≤2×n 。 而 b i = a i × a j − b j b_i=a_i \times a_j -b_j bi=ai×aj−bj,所以我们遍历 a i a_i ai(O( n ) \sqrt{n}) n)),
在遍历 a j 和 b j a_j 和 b_j aj和bj (O(n)), 答案加上 b i b_i bi 的个数就可以
代码
void solve()
{
cin>>n;
vector<PII>c(n);
vector<int>cnt(n+1);
for(int i=0;i<n;i++)
cin>>c[i].first;
for(int i=0;i<n;i++)
cin>>c[i].second;
int ans=0;
sort(c.begin(),c.end());
for(int s=1;s*s<=2*n;s++)//遍历a[i]
{
cnt.assign(n+1,0);
for(auto [a,b]:c)
{
int v=s*a-b;
if(v>=1&&v<=n)
ans+=cnt[v];
if(a==s) cnt[b]++;
}
}
cout<<ans<<endl;
}