传送
打cf就是在做英语阅读。。。
线上AB题,+补C题, D,E补不动。(@_@;)
A
题意:
给你n个h高的楼,他们在一块排列,再给你一个a,b值 意思是在 a层到b层之间都是有通向其他楼的通道,经过一个楼用1min
所有楼都一样,只有a层到b层之间有,然后有k个询问,问你从ta楼fa层到tb楼fb层需要花多少时间,在一个楼内上下楼也只要1min
思路:
分情况
1:在同一个楼内 需要abs(fa - fb)
2:在不同楼内, 如果有一方所在的楼层有通向别的楼的通道,那么则是
abs(ta - tb) + abs(fa - fb);
否则:随便找一方看它离a近还是b近 需要先走到 有通向别的楼的通道的层,在继续走
#include
using namespace std;
typedef long long ll;
ll n, h, a, b, k;
int main()
{
ios::sync_with_stdio(false);
cin >> n >> h >> a >> b >> k;
ll ta, fa, tb, fb;
for(ll i = 1;i <= k;i ++)
{
ll ans = 0;
cin >> ta >> fa >> tb >> fb;
if(ta == tb)
ans = abs(fa - fb);
else
{
if((fa >= a && fa <= b) || (fb >= a && fb <= b))
{
ans = abs(ta - tb) + abs(fa - fb);
}
else
{
ll s1 = abs(ta - tb);
ll s2, p;
if(abs(fa - a) > abs(fa - b))
{
s2 = abs(fa - b);
p = b;
}
else
{
s2 = abs(fa - a);
p = a;
}
ll s3 = abs(p - fb);
ans = s1 + s2 + s3;
}
}
cout << ans << '\n';
}
}
B
题意:
有n个学生,还以一个长度为n的序列,就是每个学生对应说的话(他们所指向的人的序号),需要你找出第一个胸前有两个印章的人,(看例子解释很容易看懂)
思路:
分情况:
1:如果需要为i的人先说了自己,即下标为i的人 a[i] = i 那么一定是这个i
2:否则按照所说的话找,不断记录前一个人所说的序号,直到第一个印章数为2的人出现,然后记录即可,模拟完所有人
一起输出答案
#include
using namespace std;
typedef long long ll;
int a[1005];
int vis[1005];
vector ans;
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i = 1;i <= n;i ++)
cin >> a[i];
for(int i = 1;i <= n;i ++)
{
memset(vis,0,sizeof(vis));
vis[i] ++;
int t = a[i];
while(1)
{
vis[t] ++;
if(vis[t] == 2)
{
ans.push_back(t);
break;
}
t = a[t];
}
}
for(int i = 0;i < ans.size();i ++)
{
if(i)
cout << " ";
cout << ans[i];
}
return 0;
}
C:
题意:
告诉你有n个学生,m个党派,其中输入数据会告诉你每个人它选了哪个党派,并且他改变主意需要花多少钱。
你的任务是确保1号党派赢的前提下使用的钱最少,
思路:
首先可以想到贪心,但是肯定不能完全正确,因为数据可能很奇葩。。。
所有我们可以枚举所有情况,保证买少的票,花最少的钱可以赢
从 0 枚举到n 取最小值
#include
using namespace std;
typedef long long ll;
pair v[3005];
ll w[3005],c[3005],ans = 1e18;
bool cmp1(pair a,pair b)
{
return a.second < b.second;
}
int main()
{
ll n,m;
cin>>n>>m;
for(ll i = 1;i <= n; ++i)
{
cin>>v[i].first>>v[i].second;
}
//按照ci 升序
sort(v + 1,v + n + 1,cmp1);
//枚举最多的得票数 从0到n
for(ll i = 0;i <= n; ++i)
{
memset(c,0x00,sizeof(c));
memset(w,0x00,sizeof(w));
//记录当前所买入的花费
ll now = 0;
//遍历所有选民
for(ll j = n;j > 0; --j)
{
//如果这个票是1号自己的,或者这个选民选的党派小于我们枚举1号党的最终选票
//就把他加上去
if(w[v[j].first] < i || v[j].first == 1)
{
w[v[j].first]++;
}
else
{ //否则就把它买了 标记已经买过 并且1号党的票数+1 加上相应的钱
now += v[j].second,c[j] = 1,w[1]++;
}
}
//想让1号党赢必须保证1号党的选票大于最多得票数 也就是 i
for(ll j = 1;j <= n; ++j)
{
if(w[1] <= i && v[j].first != 1 && c[j] == 0)
{
now += v[j].second,c[j] = 1,w[1]++;
}
}
//枚举的i 符合标准就记录花的钱 并找最小值
if(w[1] > i)
{
ans = min(ans,now);
}
}
cout<
至于D,,E
ε=ε=ε=┏(゜ロ゜;)┛
(感觉永远都在1500的水平了,菜逼)