传送门:https://codeforces.com/contest/2019
B. All Pairs Segments
题意:
首先样例解释一下:
一共有:[1,2],[1,3],[1,5],[1,6],[1,7],[2,3],[2,5],[2,6],[2,7],[3,5],[3,6],[3,7],[5,6],[5,7],[6,7]
点 1,7 在5个线段中包含,点2,4,6在9个线段中包含,点3,5在11个线段中包含
所以查询 5 时,输出2,查询9时,输出3 ...
思路:
1 2 3 5 6 7 假设一共有 n 个数
在 i 的下标中 左边一共有 i - 1 个数 ,右边有 n - i + 1,相互组合有 ( i - 1 ) * ( n - i + 1 )的贡献
并且 i 可以和右边的数组合 ,一共有 n - i 个贡献
如果没有出现在数组中,比如说 4 ,左边可以有 i - 1 个数,右边有 ( n - i + 1 ) 可以组合,所以有
( i - 1 ) * ( n - i + 1 )
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n , q;cin >> n >> q;
vector<int> a(n + 1);
for( int i = 1; i <= n; i++) cin >> a[i];
map<int,int> mp;
for( int i = 1; i <= n; i++)
{
mp[( i - 1 ) * ( n - i + 1 ) + n - i ]++;
if( i > 1 )mp[(i - 1) * ( n - i + 1 )] += ( a[i] - a[i-1] - 1 );
}
while(q--)
{
int x; cin >> x;
cout << mp[x] << " ";
}
cout << endl;
}
signed main()
{
int tt; cin >> tt;
while(tt--)solve();
return 0;
}
C. Cards Partition
题意:
思路:
假设 mx 时 数组 a 的最大值,sum 是数组 a 的总和
假设牌的大小为 x ,所有牌的数量为 x * mx,但是还有一种可能 ( sum + x - 1 ) / x * x
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n , k ; cin >> n >> k;
vector<int> a(n + 1);
for( int i = 1; i <= n; i++) cin >> a[i];
int sum = 0; int mx = 0;
for( int i = 1 ; i <= n; i++)
{
sum += a[i]; mx = max( mx , a[i] );
}
int ans = 1;
for( int i = 1 ; i <= n; i++)
{
int temp = max( mx * i , ( sum + i - 1 ) / i * i ) ;
if( temp <= sum + k ) ans = max( ans , i );
}
cout << ans << endl;
}
signed main()
{
int tt; cin >> tt;
while(tt--)solve();
return 0;
}
E. Tree Pruning
题意:
思路:(拓扑排序)
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 10;
int h[N], e[2 * N], ne[2 * N], idx;
int Size[N];
queue<int> que;
int leaf[N];
vector<int> dep[N];
bool vis[N]; int sum;
int deg[N];
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs(int u, int fa, int depth)
{
Size[u] = 1;
dep[depth].push_back(u);
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (j == fa)continue;
dfs(j, u , depth + 1 );
Size[u] += Size[j];
}
if (Size[u] == 1) {
leaf[u] = 1;
}
}
void topsort()
{
while (que.size())
{
int x = que.front();
que.pop();
if (vis[x]) continue;
vis[x] = true;
sum++;
for (int i = h[x]; i != -1; i = ne[i])
{
int j = e[i];
if (j == 1) continue;
if (--deg[j] <= 1)que.push(j);
}
}
}
void solve()
{
int n; cin >> n;
sum = 0; idx = 0;
while (que.size())que.pop();
for (int i = 0; i <= n; i++)
{
leaf[i] = Size[i] = deg[i] = 0;
vis[i] = false;
h[i] = -1;
dep[i].clear();
}
for (int i = 0; i < n - 1; i++)
{
int a, b; cin >> a >> b;
add(a, b); add(b, a);
deg[a]++; deg[b]++;
}
dfs(1, -1, 0);
int ans = 2e18;
for (int i = 1; i < n; i++)
{
int res = 0;
for (auto e : dep[i])
{
res += Size[e] - 1;
}
ans = min(ans, res + sum);
for (auto e : dep[i])
{
if (leaf[e])
{
que.push(e);
}
}
topsort();
}
cout << ans << endl;
}
signed main()
{
int tt; cin >> tt;
while (tt--)solve();
return 0;
}