cf round 549(div2)

A题,水到不能再水的题目。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
typedef pair<int, int> pir;
int a[200005];
int main()
{
	int n;
	cin >> n;
	int cntz=0,cnt1=0;
	up(i, 0, n)
	{
		scanf("%d", &a[i]);
		if (a[i] == 0)cntz++;
		else cnt1++;
	}
	int ans = 0;
	up(i, 0, n)
	{
		if (a[i] == 0)cntz--;
		else cnt1--;
		if (cntz == 0 || cnt1 == 0)
		{
			ans = i + 1;
			break;
		}
	}
	cout << ans << endl;
	return 0;
}

水题,暴力出奇迹。
我们明显可以想到的是,一般来说,有9的话各位相乘会最大,那么我们就分成两种情况暴力,
从前一位借1,然后这一位成9,和正常分解成9.。
这样就可以暴力出所有最大的答案。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
typedef pair<int, int> pir;
const int mod = 2e9 + 1;
int remax(int x)
{
	if (x == 0)
		return 1;
	if (x < 10)return x;
	return max(remax((x / 10))*(x % 10), remax(x / 10 - 1) * 9);
}
int main()
{
	int n;
	cin >> n;
	cout << remax(n) << endl;
	return 0;
}

建立一棵树,dfs跑一遍就能得到答案。
这里虽然题目说的是,每一次删除后,重新连接,但是重新连接后再dfs一遍和直接dfs一遍搜出所有满足题意的节点,是一样的。
这里题目要求自己的儿子和自己都是不尊敬长辈的,我们就将节点node开成一个是记录自己尊不尊敬,还有一个是自己的下一个节点是什么,用连接表的形式存起来。
每一个节点的儿子加和==儿子数目,而且自己不尊敬,就是题意需要删去的节点。
所以就这样dfs下去一遍就行了。然后排序输出。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
typedef pair<int, int> pir;
struct node {
	int rep,to;
};
vector<node >g[100005];
vector<int> ok;
int n;
void  dfs(int v,bool t)
{
	int cnt = 0;
	int ans = v;
	//cout << g[v].size()<<endl;
	if (g[v].size() == 0 && t)ok.push_back(v);
	else {
		up(i, 0, g[v].size())
		{
			dfs(g[v][i].to, g[v][i].rep);
			cnt += g[v][i].rep;
		}
		//cout << "v " << v << "cnt " << cnt << endl;
		if (t && cnt==g[v].size()&&cnt)ok.push_back(v);
	}
}
int main()
{
	cin >> n;
	int temp = 0;
	int v;
	int root = 0;
	upd(i, 1, n)
	{
		scanf("%d%d", &temp, &v);
		if (temp == -1) root = i;
		else g[temp].push_back(node{ v,i });
	}
	/*upd(i, 1, n)
	{
		up(j, 0, g[i].size())
		{
			cout <<"i"<<i<<"to"<< g[i][j].to <<"rep"<< g[i][j].rep << endl;
		}
	}*/
	dfs(root, 0);
	if (ok.size() == 0)
		{
			cout << -1 << endl;
			return 0;
		}
	sort(ok.begin(), ok.end());
	up(i, 0, ok.size())
		printf("%d%c", ok[i], i == n - 1 ? '\n' : ' ');
	return 0;
}

看了题解才明白过来。感觉有点点像lca
我们假设一个数组 bi表示ai再p中对应的点的前一个对应的a中离i最近的值相同的点。
很绕,举例子就是。
p 1 2 3
a 1 2 3 1 2 3
假设我们做到了i=3,i从一开始。i=4的时候,就有ai=1,对应p中有,j=1时p1即pj=1,因为p当作时环,所以他的前面一个就是3,3对应于a数组就是(离i最近的那个)a3=3,所以更新b4=3.
这样我们做出来b数组。
b 0 1 2 3 4 5
所以我们查询区间l~r的时候,从r开始沿着b往回走,有5-4-3-2-1-0,即b[b[b[b[b[…b[i]]]]]]这样,就可以找到以r为右边区间的时候,最短区间长度len,就可以更新出来l的最大值。
知道这个l的最大值大于输入的l,就是可行解。
我们这里对于这种一层套一层的用倍增思想,把每次更新看成是找父节点,向上走一步,走两步,走四部这样,类似lca的更新就能更新出最大l了。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
typedef pair<int, int> pir;
int n, m, q;
int p[200005];
int a[200005];
int dp[20][200005];
int pre[200005];
int pos[200005];
int lf[200005];
string s;
int querry(int x)
{
	dwd(j, 20, 0)
	{
		if ((1 << j)&(n-1))x = dp[j][x];
	}
	//cout << 'x' << x << endl;
	return x;
}
int main()
{
	cin >> n >> m >> q;
	upd(i, 1, n)
	{
		scanf("%d", &p[i]);
		pos[p[i]] = i;//当前pi的位置
	}
	p[0] = p[n];
	upd(i, 1, m)
	{
		scanf("%d", &a[i]);
		pre[a[i]] = i;
		//cout << "P" << p[pos[a[i]] - 1]<<endl;
		dp[0][i] = pre[p[pos[a[i]] - 1]];//找到上一个节点,0表示2^0即1,就是自己的上一个
		//cout <<"dp"<< dp[0][i] << endl;
	}
	upd(j, 0, 20)
	{
		upd(i, 1, m)
		{
			dp[j + 1][i] = dp[j][dp[j][i]];//倍增思想
		}
	}
	upd(i, 1, m)
		lf[i] = max(lf[i - 1], querry(i));//这里更新左区间的最大值。必须要更新区间长度!
	int l, r;
	while (q--)
	{
		scanf("%d %d", &l, &r);
		if (lf[r] >= l)s += '1';
		else s+='0';
		//cout << "lf" << lf[r] << endl;
	}
	cout << s;
	return 0;
}

c题
乱搞题。
对于每一个餐馆,只有四种情况,即s在餐馆之前,s+l也在前面,第二种是一前一后,第三种一后一前,第四种两后。
所以我们只需要枚举起点,然后枚举终点就可以了。
注意这里起点固定在1或者另外每一家餐馆都是一样的,因为距离是一样的,枚举出的所有终点减去起点的值与起点从哪个餐馆开始枚举是无关的。
最后更新,对于每一个l,找到lcm(l,n*m)再除以l就是圈数了。

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
typedef pair<int, int> pir;
ll n, k;
ll a, b;
int dx[] = { 1,-1,1,-1 };
int dy[] = { 1,1,-1,-1 };
ll gcd(ll a, ll b)
{
	return b == 0 ? a : gcd(b, a%b);
}
int main()
{
	cin >> n >> k;
	cin >> a >> b;
	ll ansmin = 1e16;
	ll ansmax = -1;
	up(i, 0, n)
	{
		up(j, 0, 4)
		{
			ll x = dx[j] * a;//这里直接从0开始枚举,反正从1开始美剧,x与y相减,1都是被剪掉了的
			ll y = i*k+dy[j] * b;//枚举终点
			ll len = (y - x + (n*k)) % (n*k);
			//len++;
			ansmin = min(ansmin, (n*k) / gcd((n*k), len));
			ansmax = max(ansmax, (n*k) / gcd((n*k), len));//更新最大最小值
		}
	}
	cout << ansmin <<" "<<ansmax<< endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44019404/article/details/89362345
今日推荐