T1 Fraction
题意:
输入一个数,把他分成两个互质数的和,让小的数最大.
解法:
暴力.
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long a;
cin>>a;
for(long long i=a/2;i>=0;i--)
if(__gcd(i,a-i)==1)
{
cout<<i<<" "<<a-i;
return 0;
}
}
小结:
**此类题目水题。**
T2 Maxim Buys an Apartment
题意:
n 个房间,其中有 k 个已经被出租,定义一个空房间左边或者右边有被出租的房子为好房子,求好房子的最大和最小情况。
解法:
找规律.
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long a,b;
cin>>a>>b;
if(a==b||b==0)
cout<<0<<" "<<0;
else
{
if(b>0)
cout<<1<<" ";
if(3*b>a)
cout<<a-b;
else
cout<<2*b;
}
return 0;
}
小结:
**此类题目需要特判。**
T3 Planning
题意:
机场有n架飞机,飞机i在i时起飞,由于推迟了k分钟,每一架飞机推迟一分钟损失xi元,问如何安排飞机,使损失最小.
输出最小的损失和各个飞机出发时间.
解法:
利用大头堆.
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300001;
int c[N];
int main()
{
int n,k;
cin >>n>>k;
for(int i=1; i<=n; i++)
{
cin>>c[i];
}
priority_queue < pair<int,int> > q;
ll sum=0;
for(int i=1; i<=n+k; i++)
{
if(i<=n)
{
q.push(make_pair(c[i],i));
}
if(i>k)
{
ll nn = q.top().first;
ll mm = q.top().second;
q.pop();
sum+= (ll)nn * (ll)(i-mm);
c[mm]=i;
}
}
cout << sum << '\n';
for(int i=1; i<=n; i++)
{
cout << c[i] << ' ';
}
cout << '\n';
}
小结:
**此类题目充分利用堆的原理。**
T4 Jury Meeting
题意:
给几个城市1到n,每个都要到0再回去,要待在0k天,问最少花多少钱.
解法:
暴力.
代码:
#include <bits/stdc++.h>
using namespace std
#define ll __int64
#define N 250000
struct node
{
ll d, hh, to, kk
} a[N]
ll vis[N],R[N],L[N]
ll cmp(node a, node b)
{
return a.d < b.d
}
int main()
{
ll n, m, k
while (~scanf("%I64d%I64d%I64d", &n, &m, &k))
{
memset(vis, 0, sizeof(vis))
memset(L, -1, sizeof(L))
memset(R, -1, sizeof(R))
for (ll i = 1
scanf("%I64d%I64d%I64d%I64d", &a[i].d, &a[i].hh, &a[i].to, &a[i].kk)
sort(a + 1, a + 1 + m, cmp)
ll sum = 0
ll tot = 0
for (ll i = 1
{
if (a[i].hh == 0)
continue
if (vis[a[i].hh] == 0)
{
tot += a[i].kk
sum++
vis[a[i].hh] = a[i].kk
}
else
{
if (vis[a[i].hh] > a[i].kk)
{
tot -= vis[a[i].hh]
tot += a[i].kk
vis[a[i].hh] = a[i].kk
}
}
if (sum == n)
L[i] = tot
}
sum = 0
tot = 0
memset(vis, 0, sizeof(vis))
for (ll i = m
{
if (a[i].hh != 0)
continue
if (vis[a[i].to] == 0)
{
tot += a[i].kk
sum++
vis[a[i].to] = a[i].kk
}
else
{
if (vis[a[i].to] > a[i].kk)
{
tot -= vis[a[i].to]
tot += a[i].kk
vis[a[i].to] = a[i].kk
}
}
if (sum == n)
R[i] = tot
}
ll zz = 1000000000000000000
for (ll i = m
{
if (R[i] == -1)
continue
else
{
if (R[i + 1] != -1)
R[i] = min(R[i], R[i + 1])
}
}
for (ll i = 1
{
if (L[i] == -1)
continue
else
{
ll pos = -1
ll day = a[i].d + k + 1
ll l = i + 1
ll r = m
while (r - l >= 0)
{
ll mid = (l + r) / 2
if (a[mid].d >= day)
{
r = mid - 1
pos = mid
}
else
l = mid + 1
}
if (pos == -1)
continue
else if (R[pos] != -1)
zz = min(zz, R[pos] + L[i])
}
}
if (zz == 1000000000000000000)
printf("-1\n")
else
printf("%I64d\n", zz)
}
return 0
}
小结:
**此类题目可以先手算找规律。**