样例1:
输入
2
6
1 2
2 3
3 4
1 4
1 3
2 4
5
1 2
1 2
1 3
2 3
5 6
输出
Case #1: 4
Case #2: 4
给你两个长度为 n n n的数组 A A A和 B B B,第 i i i步可以从 a i ai ai和 b i bi bi中选择一个数,求最后选出的数中,不同的数要最多。
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-08-04 11:09:22
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: [email protected]
* @ProbTitle:
*/
#include
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const int N = 2e5+5;
int f[N],a[N],b[N];
vector<int>q;
bool vis[N];
int find_set(int x){
return (x == f[x]) ? x : ( f[x] = find_set(f[x]) );
}
void solve(int n){
mem(vis,0);
sort(q.begin(),q.end());
q.erase(unique(q.begin(),q.end()),q.end());
int len = q.size();
rep(i,1,len+5) f[i] = i;
rep(i,1,n){
int x = lower_bound(q.begin(),q.end(),a[i]) - q.begin() + 1;//离散化处理
int y = lower_bound(q.begin(),q.end(),b[i]) - q.begin() + 1;
int xx = find_set(x),yy = find_set(y);
if(xx == yy){
vis[xx] = 1;//当前联通分支存在环的话则标记
}
else{
f[xx] = yy;
if(vis[xx])
vis[yy] = 1; //f[yy] = yy;xx图中存在环,我们则需要将祖先也标记上存在环
}
}
int ans = 0;
rep(i,1,len){
if(vis[i] == 0 && f[i] == i)//判断是否有环
++ans;
}
printf("%d\n",len - ans);
}
int main()
{
int t,cnt = 0;
scanf("%d",&t);
while(t--){
q.clear();
int n;
scanf("%d",&n);
rep(i,1,n){
scanf("%d%d",&a[i],&b[i]);
q.push_back(a[i]);
q.push_back(b[i]);
}
printf("Case #%d: ", ++cnt);
solve(n);
}
return 0;
}
样例:
输入
2
3
2 -1 3
3 2 1
4
3 -2 3 -1
4 2 1 2
输出
Case #1: 3 8
Case #2: 4 13
说明
For test case 1, the maximum number of visitors is 3, one of a possible solution is:
The first visitor received food 1, the profit is 2.
The second visitor received food 1, the profit is 2.
The third visitor received food 1 + food 2 + food 3, the profit is 2 + (-1) + 3.
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-08-04 11:24:49
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: [email protected]
* @ProbTitle: 高精度 + 贪心
*/
#include
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
const ll mod = 1e9 + 7;
const int N = 1e5 + 5;
int n;
struct node
{
ll num;
int id;
bool operator<(const node &A) const{
if (num != A.num)
return num < A.num;
return id < A.id;
}
} a[N];
priority_queue<node> p;
int tree[N];
void print(__int128 x)
{
if(x < 0)
{
x = -x;
putchar('-');
}
if(x > 9) print(x/10);
putchar(x%10 + '0');
}
int main()
{
//ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
scanf("%d", &t);
int cnt = 0;
while (t--)
{
while (!p.empty())
p.pop();
scanf("%d", &n);
__int128 ans = 0;
rep(i, 1, n)
{
scanf("%lld", &a[i].num);
a[i].num += a[i - 1].num;//求利润前缀最大值
a[i].id = i;
p.push(a[i]);
}
tree[0] = 0x3f3f3f;
rep(i, 1, n)
{
scanf("%d", &tree[i]);
if (tree[i] > tree[i - 1])//数量前缀最小值
tree[i] = tree[i - 1];
}
int ans2 = tree[1];
int last = 0x3f3f3f, last_num = 0;//last表示,最后一次取得的id是多少,last_num表示取了多少次
while (1)
{
ll num = p.top().num;
int id = p.top().id;
if (last < id)//表示如果最后一次取得的值小于当前id的值,last已经被取完,所以id不能取
p.pop();
else
{
if (last_num >= tree[id])//数量少的也取不了
p.pop();
else
{
__int128 a = tree[id] - last_num;
__int128 b = num;
ans += a * b;
last_num = tree[id];
last = id;
}
}
if (id == 1)
break;
}
printf("Case #%d: %d ", ++cnt, ans2);
print(ans);
printf("\n");
}
return 0;
}