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 k−1 中方案的浓度大于 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 (1−w)xi−wyi>(w−1)xj+wyj构造两个序列 A = { ( 1 − w ) x i − w y i } A=\{(1-w)x_i -wy_i\} A={(1−w)xi−wyi}, B = { ( w − 1 ) x j + w y j } B = \{ (w-1)x_j+wy_j \} B={(w−1)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;
}