AtCoder Beginner Contest 294

A - Filter

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;

int n, x;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n;
	while(n--){
		cin >> x;
		if(x%2 == 0)
			cout << x << " ";
	}
	cout << endl;
	return 0;
}


B - ASCII Art

题意:

二维数组,对于每一行,将 0 变为 .1~26 变为 A~Z

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;

int n, m;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m;
	while(n--){
		string s = "";
		int x;
		for(int i = 1; i <= m; i++){
			cin >> x;
			if(x == 0)
				s += '.';
			else
				s += (char)(x + 'A' - 1);
		}
		cout << s << endl;
	}
	return 0;
}


C - Merge Sequences

题意:

给定两个升序序列 A , B A,B A,B A , B A,B A,B 中元素各不相同,合并成升序序列 C C C,询问 A , B A,B A,B 中元素在 C C C 中位置

解析:

双指针,将 A , B A,B A,B 放到 C C C 中,放到时候记录以下位置

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;

int n, m;
int a[maxn], b[maxn];
int posa[maxn], posb[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	for(int j = 1; j <= m; j++)
		cin >> b[j];
	int i = 1, j = 1, pos = 1;
	for(; i <= n; i++){
		while(a[i] > b[j] && j <= m){
			posb[j++] = pos++;
		}
		posa[i] = pos++;
	}
	while(i <= n)
		 posa[i++] = pos++;
	while(j <= m)
		posb[j++] = pos++;
		
		
	for(int i = 1; i <= n; i++){
		if(i != 1)
			cout << " ";
		cout << posa[i];
	}
	cout << endl;
	for(int i = 1; i <= m; i++){
		if(i != 1)
			cout << " ";
		cout << posb[i];
	}
	return 0;
}


D - Bank

题意:

n n n 个人,发生 q q q 次事件:

  • 1 呼叫 编号最小的未呼叫过的人
  • 2 x 编号为 x 的人报道
  • 3 呼叫 呼叫过但未报道的 标号最小的人

对于事件3,输出呼叫标号

解析:

s e t set set 维护 呼叫过但未报道的编号

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;

int n, q;
set<int> s;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> q;
	int minn = 1;
	while(q--){
		int op;
		cin >> op;
		if(op == 1){
			s.insert(minn);
			minn++;
		}
		else if(op == 2){
			int a; cin >> a;
			s.erase(a);
		}
		else if(op == 3){
			int res = *(s.begin());
			//cout << "ans = ";
			cout << res << endl;
		}
	}
	return 0;
}


E - 2xN Grid

2 × n 2\times n 2×n 的格子,询问列上元素相同的列的数目
( v , l e n ) (v,len) (v,len) 形式描述。有 l e n len len 个连续的 v v v

解析:

以分割点进行匹配

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<ll, ll> pll;

pll a[maxn];
pll b[maxn];
ll len, n, m;
int	main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> len >> n >> m;
	for(int i = 1; i <= n; i++)
		cin >> a[i].fi >> a[i].se;
		
	for(int i = 1; i <= m; i++)
		cin >> b[i].fi >> b[i].se;
	int i = 1, j = 1;
	ll ans = 0;
	while(1){
		ll x = min(a[i].se, b[j].se);
		if(a[i].fi == b[j].fi)
			ans += x;
		a[i].se -= x;
		b[j].se -= x;
		
		if(a[i].se == 0)
			i++;
		if(b[j].se == 0)
			j++;
		
		if(i == n+1 || j == m+1)
			break;
	}
	cout << ans << endl;
	return 0;
}                         


F - Sugar Water 2

题意:

给定两组糖水,从每一组选出一杯混合,询问所有方案中浓度第 k k k 高的浓度

解析:

二分答案。

对于当前浓度 w w w,检查是否有 k − 1 k-1 k1 中方案的浓度大于 w w w

但暴力检查的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

对于一种方案 ( i , j ) (i,j) (i,j),假设浓度大于 w w w,则: x i + x j x i + x j + y i + y j > w \frac{x_i+x_j}{x_i+x_j+y_i+y_j} > w xi+xj+yi+yjxi+xj>w 把含 i i i 放在一边,含 j j j 放在另一边: ( 1 − w ) x i − w y i > ( w − 1 ) x j + w y j (1-w)x_i -wy_i > (w-1)x_j+wy_j (1w)xiwyi>(w1)xj+wyj构造两个序列 A = { ( 1 − w ) x i − w y i } A=\{(1-w)x_i -wy_i\} A={(1w)xiwyi} B = { ( w − 1 ) x j + w y j } B = \{ (w-1)x_j+wy_j \} B={(w1)xj+wyj},排序后统计 A [ p ] > B [ q ] A[p] > B_[q] A[p]>B[q] 的数目。

时间复杂度 O ( 50 n l o g n ) O(50 nlogn) O(50nlogn)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
const db eps = 1e-10;
typedef pair<db, db> pdd;

pdd a[maxn], b[maxn];
ll n, m, k;
vector<db> ta, tb;

bool check(db x){
	ta.clear();
	tb.clear();
	for(int i = 1; i <= n; i++)
		ta.push_back((1.0-x)*a[i].fi - x*a[i].se);
	for(int i = 1; i <= m; i++)
		tb.push_back((x-1.0)*b[i].fi + x*b[i].se);	
	sort(ta.begin(), ta.end());
	sort(tb.begin(), tb.end());
	
	int i = 0, j = 0;
	ll cnt = 0;
	for(; i < n; i++){
		while(tb[j] < ta[i] && j < m)
			j++;
		cnt += j;
	}
	return cnt <= (k-1);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m >> k;
	for(int i = 1; i <= n; i++)
		cin >> a[i].fi >> a[i].se;
	for(int i = 1; i <= m; i++)
		cin >> b[i].fi >> b[i].se;
		
	db l = 0, r = 1;
	int cnt = 50;
	while(cnt--){
		db mid = (l+r) / 2;
		if(check(mid))
			r = mid;
		else
			l = mid;
	} 
	cout << fixed << setprecision(12) << r*100.0 << endl;
	return 0;
}


G - Distance Queries on a Tree

题意:

给定一棵树,两种操作:

  • 修改某一条边的边权
  • 询问两点之间的距离

解析:

d ( u , v ) = d i s ( u ) + d i s ( v ) − 2 d i s ( l c a ) d(u,v) = dis(u)+dis(v)-2dis(lca) d(u,v)=dis(u)+dis(v)2dis(lca)

线段树维护每个节点到根节点的距离

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define fi first
#define se second
const int maxn = 2e5+10;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;

#define int ll
inline int ls(int x){return x << 1;}
inline int rs(int x){return x << 1 | 1;}

struct sgt{
	ll v, tag;
}t[maxn << 2];
struct edge{
	int to, nxt;
	ll w;
}e[maxn << 1];
struct node{
	int fr, to;
	ll w;
	node(int fr, int to, ll w) : fr(fr), to(to), w(w){} 
};
vector<node> edg;
int head[maxn], tot;
int dep[maxn], top[maxn], siz[maxn], fa[maxn], son[maxn];
ll dis[maxn];
int dfn[maxn], pre[maxn], dfntot;
ll a[maxn];
int n, q;
void add(int a, int b, ll c){
	e[++tot].nxt = head[a];
	e[tot].to = b;
	e[tot].w = c;
	head[a] = tot;
}
void dfs1(int u, int p){
	dep[u] = dep[p] + 1;
	siz[u] = 1;
	fa[u] = p;
	for(int i = head[u]; i; i = e[i].nxt){
		int v = e[i].to;
		if(v == p)
			continue;
		dis[v] = dis[u] + e[i].w;
		a[v] = e[i].w;
		dfs1(v, u);
		siz[u] += siz[v];
		if(siz[v] > siz[son[u]])
			son[u] = v;
	}
}
void dfs2(int u, int tp){
	dfn[u] = ++dfntot;
	pre[dfntot] = u;
	top[u] = tp;
	if(son[u])
		dfs2(son[u], tp);
	for(int i = head[u]; i; i = e[i].nxt){
		int v = e[i].to;
		if(v == fa[u] || v == son[u])
			continue;
		dfs2(v, v);
	}
}
void pushup(int k){
	t[k].v = max(t[ls(k)].v, t[rs(k)].v);
}
void pushdown(int k){	
	if(t[k].tag){
		t[ls(k)].tag += t[k].tag;
		t[rs(k)].tag += t[k].tag;
		t[ls(k)].v += t[k].tag;
		t[rs(k)].v += t[k].tag;
		t[k].tag = 0;
	} 
}
void build(int k, int l, int r){
	t[k].tag = 0;
	if(l == r){
		t[k].v = dis[pre[l]];
		return;
	}
	int mid = (l+r) >> 1;
	build(ls(k), l, mid);
	build(rs(k), mid+1, r);
	pushup(k);
}
void update(int k, int l, int r, int x, int y, ll w){ //区间加 
	if(x <= l && y >= r){
		t[k].v += w;
		t[k].tag += w;
		return;
	}
	int mid = (l+r) >> 1;
	pushdown(k);
	if(x <= mid)
		update(ls(k), l, mid, x, y, w);
	if(y > mid)
		update(rs(k), mid+1, r, x, y, w);
	pushup(k);
}
ll query(int k, int l, int r, int x, int y){
	if(x <= l && y >= r)
		return t[k].v;
	pushdown(k);
	int mid = (l+r) >> 1;
	ll res = -1;
	if(x <= mid)
		res = max(res, query(ls(k), l, mid, x, y));
	if(y > mid)
		res = max(res, query(rs(k), mid+1, r, x, y));
	return res;
}
void Change(int k, ll w){
	node s = edg[k-1];
	int u = s.fr;
	int v = s.to;	
	if(fa[v] != u)
		swap(u, v);
	ll d = w - a[v];
	a[v] = w;
	update(1, 1, n, dfn[v], dfn[v] + siz[v] -1, d);
}
int LCA(int u, int v){
	while(top[u] != top[v]){
		if(dep[top[u]] < dep[top[v]])
			swap(u, v);
		u = fa[top[u]];
	}
	if(dep[u] < dep[v])
		swap(u, v);
	return v;
}
ll query(int u, int v){
	int lca = LCA(u, v);
	ll disu = query(1, 1, n, dfn[u], dfn[u]);
	ll disv = query(1, 1, n, dfn[v], dfn[v]);
	ll dislca = query(1, 1, n, dfn[lca], dfn[lca]);
	
	return disu - dislca + disv - dislca;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n;
	for(int i = 1; i < n; i++){
		int a, b, c;
		cin >> a >> b >> c;
		edg.push_back(node(a, b, c));
		add(a, b, c);
		add(b, a, c);
	}
	dfs1(1, 0);
	dfs2(1, 1);
	build(1, 1, n);
	
	cin >> q;
	int op, k, w, u, v;
	while(q--){
		cin >> op;
		if(op == 1){
			cin >> k >> w;
			Change(k, w);
		}		
		else if(op == 2){
			cin >> u >> v;
			ll res = query(u, v);
			//cout << "ans = ";
			cout << res << endl;
		}
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值