Codeforces Round #791 (Div. 2) A B C D


一、A

思路 : 这个我的数学垃圾,没有推出来那个式子,然后就是硬试出来的,这个n要么是4的整数倍,要么 mod 4 = 2 要么是6的整数倍,要mod 6 = 4 要么mod 6 = 2,其他情况都是不可能的 ,推式子的话我看别的博客里面有,这里就不推了

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 20;

void solve()
{
	
	int n; cin >> n;
	if(n % 4 != 0 && n % 4 != 2 && n % 6 != 0 && n % 6 != 2 && n % 6 != 4) cout << "-1" << endl;
	else if(n < 4) cout << "-1" << endl; //特判一下2
	else
	{
		// 最多就先搞4个轮子的
		int mi,mx;
		mi = n / 6;
		mx = n / 4;
		if(n % 6 != 0)
		mi++;
		
		
		cout << mi << ' ' << mx << endl;
	}
}

signed main() 
{

	ios;int T; cin >> T; 
	while(T -- ) solve();
	
    return 0;
}

二、B

思路 题目是 单点修改,区间修改,区间查询,然后发现区间查询和区间修改只有一个区间就是1~n,当时一开始想的是树状数组,后来发现太复杂了,又看了一遍,发现可以用一个变量last存一下区间修改的数字,
当单点修改的时候,如果last变了,就用last,如果last没变或者已经使用过了,就用a[v]

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 2e5 + 100,inf = -1e9 - 100;
int a[N];
int w[N];

void solve()
{
	
	int n,q; cin >> n >> q;
	for(int i = 1;i <= n;i ++ ) cin >> a[i];
	
	int sum = 0,last = 0,cnt = 0;
	for(int i = 1;i <= n;i ++ ) sum += a[i];
	
	while(q -- )
	{
		int op,x,v; cin >> op;
		if(op == 1)
		{
			cin >> v >> x;
			if(w[v] != cnt)
			sum += (x - last);
			else
			sum += (x - a[v]);
			
			cout << sum << endl;
			a[v] = x;
			w[v] = cnt;
		}
		else
		{
			cin >> x;
			
			sum = x * n;
			last = x;
			cnt++;
			
			cout << sum << endl;
		}
	}
}

signed main() 
{

	ios;int T = 1;
	while(T -- ) solve();
	
    return 0;
}

三、C

思路,从题目可以知道我们如果想要的区间被全部摧毁,要么每一列都存在R,要么每一行都存在R,满足其中一个即可,所以可以用树状数组,开两个树状数组,一个存行,一个存列,

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const int N = 1e5 + 100,inf = -1e9 - 100;
int trr[N],trc[N],column[N],row[N];
int n,q; 
int lowbit(int x)
{
	return x & -x;
}

void add(int x,int c,int st)
{
	if(st)
	for(int i = x;i <= n;i += lowbit(i))
	trr[i] += c;
	else
	for(int i = x;i <= n;i += lowbit(i))
	trc[i] += c;
}

int sum(int x,int st)
{
	int ans = 0;
	if(st)
	for(int i = x;i >= 1;i -= lowbit(i))ans += trr[i];
	else
	for(int i = x;i >= 1;i -= lowbit(i))ans += trc[i];
	
	return ans;
}

void solve()
{
	cin >> n >> q;

	while(q -- )
	{
		int op,x1,y1,x2,y2; cin >> op;
		if(op == 1)
		{
			cin >> x1 >> y1;
			if(row[x1] == 0)
			{
				add(x1,1,1);
			}
			
			if(column[y1] == 0)
			{
				add(y1,1,0);
			}
			
			row[x1]++;
			column[y1]++;
		}
		else if(op == 2)
		{
			cin >> x1 >> y1;
			row[x1]--;
			column[y1]--;
			if(row[x1] == 0)
			{
				add(x1,-1,1);
			}
			
			if(column[y1] == 0)
			{
				add(y1,-1,0);
			}
			
		}
		else
		{
			cin >> x1 >> y1 >> x2 >> y2;
			int r = x2 - x1 + 1;
			int c = y2 - y1 + 1;
			
			int r1 = sum(x2,1) - sum(x1 - 1,1);
			int c1 = sum(y2,0) - sum(y1 - 1,0);
			
			if(r == r1 || c == c1) cout << "Yes" << endl;
			else cout << "No" << endl;
		}
	}
	 
}

signed main() 
{

	ios;int T = 1;
	while(T -- ) solve();
	
    return 0;
}

四、D

思路 因为是要权值最大值最小,所以就是二分一下权值, mid就是此时枚举的最大的权值,然后重新建立一张图,比mid大的权值的点不要,因为是二分,规定了当前的最大权值是mid,然后拓扑序列来判断一下有没有回路,有的话最大权值取mid就一定可以,或者 当前的最长的路径的长度 >= k的话也可以,其他情况就不行

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define all(x) x.begin(),x.end()
#define PII pair<int,int>
#define ios ios::sync_with_stdio(false);cin.tie(0)
#define x first
#define y second
#define pb push_back
using namespace std;
const int N = 2e5 + 100,inf = -1e9 - 100;
vector<PII> e;
int w[N],d[N],dist[N]; 
int n,m,k;
vector<int> res[N];
bool check(int num)
{
	queue<int> q;

	for(int i = 0;i <= n;i ++ )
	{
		d[i] = 0; dist[i] = 0;
		res[i].clear();
	} 
	
	for(int i = 0;i < e.size();i ++ )
	{
		int u = e[i].x,v = e[i].y;
		if(w[u] > num || w[v] > num) continue;
		
		d[v]++;
		res[u].pb(v);
	}
	
	for(int i = 1;i <= n;i ++ )
	{
		if(w[i] <= num && d[i] == 0)
		{
			q.push(i);
			dist[i] = 1;
		}
		
	}
	int mx = -1;
	while(q.size())
	{
		int t = q.front(); q.pop();
		mx = max(mx,dist[t]);
	
		for(int i = 0;i < res[t].size();i ++ )
		{
			int j = res[t][i];
			d[j]--;
		
			
			if(d[j] == 0)
			{
				q.push(j);
				dist[j] = dist[t] + 1;
			}  
		}
	}
	

	if(mx >= k) return true;
	else 
	{
	    for(int i = 1;i <= n;i ++ )
	    {
	        if(w[i] <= num && d[i] != 0)
	        {
	            return true;
	        }
	    }

	 return false; 
	}

	
}

void solve()
{
	cin >> n >> m >> k;
	for(int i = 1;i <= n;i ++ )  cin >> w[i];
	while(m -- )
	{
		int u,v; cin >> u >> v;
		e.pb({u,v});
		
	}
	//二分最大值
	// 在子图中判断有没有环,有环一定是true 没有的话 就要判断最长的链的长度是不是 >= k
	// 比mid权值大的都不能用
	 
	int l = 0,r = 1e9;

	
	while(l <= r)
	{
		int mid = l + r >> 1;
		
		if(check(mid))
		{
			r = mid - 1;
		}
		else
		{
			l = mid + 1;
		}
	}
	
	if(l == 1e9 + 1)
	cout << "-1" << endl; 
	else
	cout << l << endl;
	

	 
}

signed main() 
{

	ios;int T = 1;
	while(T -- ) solve();
	
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值