1. 程式人生 > 其它 >Codeforces Round #791 (Div. 2)解題報告

Codeforces Round #791 (Div. 2)解題報告

A. AvtoBus

題意:有兩種車,一種車4輪,另一種6輪,給你輪子的數量,猜出能恰好組成的車輛數量的最大和最小,如果湊不出就輸出-1
分析: 顯而易見奇數個輪子肯定不恰好能湊成若干車輛,再考慮偶數情況,將6看作兩個2加一個2,4看作兩個2,那麼所有大於4的偶數都可以看作是若干個2組成的,那麼所有的偶數都可以由4和6組成
故輸出-1的條件為x < 4 || x & 1,最大的計算:肯定能組成的話,先儘量組成4輪的,如果有剩餘,肯定剩2,隨便找一個4輪的安成6輪的,所以maxv = x / 4,最小的計算:先儘量組成6輪的,如果有剩餘那麼剩下的不是2就是4,拉出一輛6輪的組成倆4輪或一4一6,車輛數 + 1,所以minv = x / 6 + (x % 6 != 0);
ac 程式碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,m,x,y,k,idx;
int row[N],col[N];
set<int> r;
set<int> co;

int main()
{
	ios;
	int t;
	cin >> t;
	while(t --)
	{
		LL x;
		cin >> x;
		if(x < 4 || x & 1) cout << -1 << endl;
		else 
		{
			LL maxv = x / 4, minv = x / 6 + (x % 6 != 0);
			cout << minv << " " << maxv << endl;
		}
	}
	return 0;
}

B. Stone Age Problem

題意:給你一個數組,定義以下兩個操作:
1.令a[pos] = x;
2.令所有數變成x
每次操作都要輸出當前陣列的總和
分析:模擬
ac程式碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 2000010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,k;
int a[N];
string s,p;
LL sum = 0,last = 0;
bool flag = false,st[N];
int main()
{
	ios;
	cin >> n >> k;
	
	for(int i = 1;i <= n;i ++) cin >> a[i],sum += a[i];

	while(k --)
	{
		int t,pos,x;
		cin >> t;
		if(t == 1)
		{
			cin >> pos >> x;
			if(!flag)
			{
				sum -= a[pos];
				a[pos] = x;
				sum +=  a[pos];
			}
			else
			{
				if(!st[pos])
				{
					sum -= last - x;
					a[pos] = x;
					st[pos] = true;
				}
				else 
				{
					sum -= a[pos] - x;
					a[pos] = x;
				}
				

			}
			cout << sum << endl;

		}
		else
		{
			flag = true;
			memset(st,0,sizeof(bool) * (n + 4));
			cin >> x;
			sum = 1LL * x * n;
			last = x;
			cout << sum << endl;
		}
	}
	return 0;
}

C. Rooks Defenders

題意:給定一個\(n * n\) 的棋盤,定義以下三個操作:
1.在(x,y)處放一個棋子
2.在(x,y)處取走棋子
3.問 以\((x_1,y_1)\)為左上角\((x_2,y_2)\)為右下角的區域是否每個格子都被攻擊
攻擊條件:一個格子所在行或所在列有棋子就被攻擊
在進行操作3後,需回答
分析:維護空行和空列兩個有序集合,

version 1

採用二叉搜尋樹來維護,每次詢問對有序行集合進行查詢大於x1的最小元素,對有序列集合進行查詢大於y1的最小元素,如果行大於x2,或列大於y2,說明整個區域都被攻擊,
ac程式碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,m,x,y,k,idx;
int row[N],col[N];
set<int> r;
set<int> co;
int main()
{
	ios;
	cin >> n >> k;
	for(int i = 1;i <= n;i ++) co.insert(i),r.insert(i);

	while(k --)
	{
		int t,a,b,c,d;
		cin >> t;
		if(t == 1)
		{
			cin >> a >> b;
			row[a] ++,col[b] ++;
			
			if(row[a] == 1) r.erase(a);
			if(col[b] == 1) co.erase(b);
		}
		else if(t == 2)
		{
			cin >> a >> b;
			row[a] -- , col[b] --;
			if(!row[a]) r.insert(a);
			if(!col[b]) co.insert(b);
		}
		else
		{
			cin >> a >> b >> c >> d;
			set<int>::iterator A = r.lower_bound(a),B = co.lower_bound(b);
			if(A == r.end() || B == co.end()) cout << "YES" << endl;
			else if(* A > c || * B > d) cout << "YES" << endl;
			else cout << "NO" << endl;
		}
	}
	return 0;
}

version 2

用兩個樹狀陣列維護行與列的空行
ac程式碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include <sstream>
#include <fstream> 
#include <cmath>
#include <iomanip>
#include <unordered_map>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl '\n'
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
 
const int N = 200010,M = 500010,INF = 0x3f3f3f3f,mod = 1e9 + 7 ;
const double INFF = 0x7f7f7f7f7f7f7f7f;

int n,m,x,y,k,idx;
int row[N],col[N];
int tr1[N],tr2[N];

int lowbit(int x)
{
	return x & -x;
}

void add(int tr[],int x,int v)
{
	for(int i = x;i < N;i += lowbit(i)) tr[i] += v;
}

int query(int tr[],int x)
{
	int res = 0;
	for(int i = x;i;i -= lowbit(i)) res += tr[i];
	return res;
}

int main()
{
	ios;
	cin >> n >> k;
	while(k --)
	{
		int t,a,b,c,d;
		cin >> t;
		if(t == 1) 
		{
			cin >> a >> b;
			row[a] ++, col[b] ++;
			if(row[a] == 1) add(tr1,a,1);
			if(col[b] == 1) add(tr2,b,1);
		}
		else if(t == 2)
		{
			cin >> a >> b;
			row[a] --,col[b] --;
			if(row[a] == 0) add(tr1,a,-1);
			if(col[b] == 0) add(tr2,b,-1);
		}
		else
		{	
			cin >> a >> b >> c >> d;
			x = query(tr1,c) - query(tr1,a - 1);
			y = query(tr2,d) - query(tr2,b - 1);
			if(x >= c - a + 1 || y >= d - b + 1) cout << "YES" << endl;
			else cout << "NO" << endl;
		}
	}
	return 0;
}