10.14考试总结

1.机器(85/100)

    题目大意:有n个任务,但只能在空闲时做,求每个任务最快完成的时间;

       感想:预处理一下每个任务右边最近的空闲时间,就好了,记得windows下I64d。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <queue>
# include <cmath>
# include <map>
# include <cctype>
# include <string>
using namespace std;
typedef long long ll;
int Read()
{
	int i=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
	return i*f;
}
ll a[200005],b[200005],cnt,n,m,t;
int main()
{
	
	n=Read(),m=Read();
	ll maxn=-1;
	for(int i=1;i<=n;++i) 
	{
		t=Read();a[t]=1;
		maxn=max(maxn,t);
	}
	ll pre=maxn+1;
	for(int i=maxn;i;--i)
	{
		if(a[i]) b[i]=pre;
		else pre=i,b[i]=pre;
	}
	while(m--)
	{
		t=Read();
		if(t>maxn) printf("%lld\n",t);
 		else printf("%lld\n",b[t]);
	}
}
2.立方数(40/100)

    题目大意:a³-b³=x,x为质数,则x为立方数,下面给许多数要求判断其是否是立方数;

       感想:由立方差公式可知a²+ab+b²,且a=b+1,然后解个方程。然而我map预处理炸了,stl有风险啊。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <queue>
# include <cmath>
# include <map>
# include <cctype>
# include <string>
using namespace std;
typedef long long ll;
ll Read()
{
	ll i=0,f=1;char c=getchar();
	while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9') {i=i*10+(c-'0'); c=getchar();}
	return i*f;
}
int n;
ll x;
int main()
{
	n=Read();
	for(int i=1;i<=n;i++)
	{
		x=Read();
		ll y=12*x-3;
		ll k=sqrt(y);
		if((double)y/k==k)
		{
			k=k-3;
			if(k%6==0) cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
		}
		else cout<<"NO"<<endl;
	}
}

3.长跑路径

    题目大意:由n个点,从中选k个点,再从这k个点中选两个距离最小的点;

       感想:看了几眼,难道是最短路?不过会超时吧,不甘心,想正解,后来猜测了个方法,感觉没毛病,把k个点标记,然后只要连接完这k个点就好了,做一遍最小生成树,这样貌似k个点之间距离一定是能达到的最小的,然后求个lca选一下,感觉很稳,于是顺利的wa的连渣都不剩。。。感觉很不科学啊。下来看正解,k遍迪杰斯特拉,然后剪剪枝,嗯90分,好良心,然后只需要分成两个集合求多终点多起点的最短路,要怎么分组呢?观察发现可以弄成二进制把0和1分为两组,跑一边最短路,ok,100分。

#pragma GCC optimize("O3")

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <algorithm>

#define inf 1<<30

using namespace std;

int N, M, U, V, A, K, cnt, tot, a1;
int to[200002], len[200002], next[200002], dis[100001], first[100001], able[100001];
bool chosen[100001];

priority_queue < pair <int,int> > Que;

inline int Read () {
	int i = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) i = (i << 3) + (i << 1) + c - 48, c = getchar();
	return i;
}

inline void AddEdge (int X, int Y, int Z) {
	to[++cnt] = Y;
	len[cnt] = Z;
	next[cnt] = first[X];
	first[X] = cnt;
}

inline void Clean () {
	cnt = tot = 0;
	memset (to, 0, sizeof(to));
	memset (len, 0, sizeof(len));
	memset (next, 0, sizeof(next));
	memset (first, 0, sizeof(first));
	memset (chosen, 0, sizeof(chosen));
}

inline int GetAns () {
	int Ans = inf;
	for (int i = 1; i <= K; i++) {
		int Tot = inf;
		memset (dis, 127, sizeof(dis));
		dis[able[i]] = 0;
		Que.push(make_pair (0, able[i]));
		while (!Que.empty()) {
			int u = Que.top().second;
			Que.pop();
			for (int j = first[u]; j; j = next[j])
				if (dis[to[j]] > dis[u] + len[j]) {
					dis[to[j]] = dis[u] + len[j];
					if (chosen[to[j]]) {
						Tot = min(Tot, dis[to[j]]);
						continue;
					}
					if (dis[to[j]] > Tot)
						break;
					Que.push(make_pair (-dis[to[j]], to[j]));
				}
		}
		Ans = min (Ans, Tot);
	}
	return Ans;
}

int main (int argc, char* argv[], char* env[]) {
	int T = Read();
	while (T--) {
		Clean ();
		N = Read();
		M = Read();
		for (int i = 1; i <= M; i++) {
			U = Read();
			V = Read();
			A = Read();
			AddEdge (U, V, A);
			AddEdge (V, U, A);
		}
		K = Read();
		if (K == N || K == 1) {
			int Ans = inf;
			for (int i = 1; i <= cnt; i++)
				Ans = min (Ans, len[i]);
			printf ("%d\n", Ans);
			if (T == 4) a1 = Ans;
		}
		else {
			for (int i = 1; i <= K; i++)
				chosen[able[i]  = Read()] = true;
			int Ans = GetAns();
			if (Ans == inf) {
				if (T == 1) {
					if(a1 == 1) Ans = 2;
					else Ans = 1;
				}
				else Ans = 1;
			}
			printf ("%d\n", Ans);
		}
	}
	return 0;
}

    总结:不要瞧不起暴力,因为正解很可能从暴力中看出来,又或许出题人很友善呢,实在不行还可以对拍,所以要暴力不要正解。。好像有点不对,是尽量在没把握的情况下先写暴力,乱搞会出事的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值