2022NOIP A层联测34

A. bs 串

发现找 bsbb 或者 sbss

于是二分+并查集维护

code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 500005;
int n, m, q, col[maxn];
int cnt, tot;
struct edge {
    int u, v, tim;
} com[maxn], e[maxn];
struct DSU {
    int f[maxn], siz[maxn];
    vector<int> del, tim;
    void init() {
        for (int i = 1; i <= n; ++i) f[i] = i, siz[i] = 1;
    }
    int fa(int x) { return f[x] == x ? x : fa(f[x]); }
    void merge(int x, int y, int now) {
        x = fa(x);
        y = fa(y);
        if (x == y)
            return;
        if (siz[x] < siz[y])
            swap(x, y);
        del.push_back(y);
        tim.push_back(now);
        siz[x] += siz[y];
        f[y] = x;
    }
    void Del(int Tim) {
        while (tim.size()) {
            if (tim.back() <= Tim)
                return;
            int y = del.back(), x = f[y];
            del.pop_back();
            tim.pop_back();
            siz[x] -= siz[y];
            f[y] = y;
        }
    }
} S;
int mid, pe;
bool check() {
    while (pe < tot && e[pe + 1].tim <= mid) {
        ++pe;
        S.merge(e[pe].u, e[pe].v, e[pe].tim);
    }
    S.Del(mid);
    while (pe && e[pe].tim > mid) --pe;
    for (int i = 1; i <= cnt && com[i].tim <= mid; ++i) {
        if (S.fa(com[i].u) == S.fa(com[i].v))
            return true;
    }
    return false;
}
char s[maxn];
int main() {
    freopen("bssb.in", "r", stdin);
    freopen("bssb.out", "w", stdout);
    scanf("%d%d%d", &n, &m, &q);
    scanf("%s", s + 1);
    for (int i = 1; i <= n; ++i) col[i] = s[i] == 's';
    S.init();
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        if (col[u] == col[v]) {
            com[++cnt] = { u, v, 0 };
        } else
            S.merge(u, v, 0);
    }
    for (int i = 1; i <= q; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        if (col[u] == col[v]) {
            com[++cnt] = { u, v, i };
        } else
            e[++tot] = { u, v, i };
    }
    int l = 1, r = q, ans = q + 1;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (check())
            r = mid - 1, ans = mid;
        else
            l = mid + 1;
    }
    for (int i = 1; i < ans; ++i) printf("No\n");
    for (int i = ans; i <= q; ++i) printf("Yes\n");
    return 0;
}

B. 英语作文

考场推了一堆奇怪的东西

最开始想维护句子,但是发现位置无法很好维护

根据数据范围猜测为线性做法,于是考虑顺序转移

然后把想到的情况都写下来

就有了 主, 主谓, 句, 句谓, 句谓主 。。。。。。。。

然后经过画图,发现最终结尾元素相同的完全一致

于是只用记录以主,谓,宾三者结尾的方案数

答案是宾语结尾的

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 500005;
int n, m, q, col[maxn];
int cnt, tot;
struct edge{int u, v, tim;}com[maxn], e[maxn];
struct DSU{
	int f[maxn], siz[maxn];
	vector<int>del, tim;
	void init(){for(int i = 1; i <= n; ++i)f[i] = i, siz[i] = 1;}
	int fa(int x){return f[x] == x ? x : fa(f[x]);}
	void merge(int x, int y, int now){
		x = fa(x); y = fa(y);
		if(x == y)return;
		if(siz[x] < siz[y])swap(x, y);
		del.push_back(y); tim.push_back(now);
		siz[x] += siz[y]; f[y] = x;
	}
	void Del(int Tim){
		while(tim.size()){
			if(tim.back() <= Tim)return;
			int y = del.back(), x = f[y];
			del.pop_back(); tim.pop_back();
			siz[x] -= siz[y]; f[y] = y;
		}
	}
}S;
int mid, pe;
bool check(){
	while(pe < tot && e[pe + 1].tim <= mid){
		++pe; S.merge(e[pe].u, e[pe].v, e[pe].tim);
	}
	S.Del(mid);
	while(pe && e[pe].tim > mid)--pe;
	for(int i = 1; i <= cnt && com[i].tim <= mid; ++i){
		if(S.fa(com[i].u) == S.fa(com[i].v))return true;
	}
	return false;
}
char s[maxn];
int main(){
	freopen("bssb.in","r",stdin);
	freopen("bssb.out","w",stdout);
	scanf("%d%d%d",&n,&m,&q);
	scanf("%s",s + 1);
	for(int i = 1; i <= n; ++i)col[i] = s[i] == 's';
	S.init();
	for(int i = 1; i <= m; ++i){
		int u, v; scanf("%d%d",&u,&v);
		if(col[u] == col[v]){ com[++cnt] = {u, v, 0};}
		else S.merge(u, v, 0);
	}
	for(int i = 1; i <= q; ++i){
		int u, v; scanf("%d%d",&u,&v);
		if(col[u] == col[v]){com[++cnt] = {u, v, i};}
		else e[++tot] = {u, v, i};
	}
	int l = 1, r = q, ans = q + 1;
	while(l <= r){
		mid = (l + r) >> 1;
		if(check())r = mid - 1, ans = mid;
		else l = mid + 1;
	}
	for(int i = 1; i < ans; ++i)printf("No\n");
	for(int i = ans; i <= q; ++i)printf("Yes\n");
	return 0;
}

C. 计算器

发现一段操作可以看成先右移 a, 再左移 b ,再加上 c

那么对于 lowbit 相同的数,他们的变化是相同的

于是可以拿线段树维护这个东西

合并两个三元组 (a,b,c)(d,e,f)

考虑到

x2a2b2d2f

b,d 的大小关系,于是有两种情况

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 200005;
int lim;
int n, m, q, cal[maxn];
char s[maxn];
struct note{
    int a, b, c;
    note(){a = b = c = 0;}
	note(int _a, int _b, int _c){a = _a, b = _b, c = _c;}
    int calc(int x){return x >> a << b | c;}
    friend note operator + (const note &x, const note &y){
       if(x.b < y.a)return {x.a + y.a - x.b, y.b, y.c + (x.c >> y.a << y.b)};
       else return {x.a , x.b - y.a + y.b , y.c + (x.c >> y.a << y.b)};
    }
};
void build(note a[], int op){
    switch(op){
        case 1: a[0] = {0, 0, 0}; for(int i = 1; i < m; ++i)a[i] = {1, 0, 0}; break;
        case 2: for(int i = 0; i < m - 1; ++i)a[i] = {0, 1, 0}; a[m - 1] = {0, 0, 0}; break;
        case 3: for(int i = 0; i < m - 1; ++i)a[i] = {0, 1, 1}; a[m - 1] = {0, 0, 0}; break;
        case 4: for(int i = 0; i < m; ++i)a[i] = {i, 0, 0}; break;
        case 5: for(int i = 0; i < m; ++i)a[i] = {0, m - i - 1, 0}; break;
        case 6: for(int i = 0; i < m; ++i)a[i] = {0, m - i - 1, (1 << (m - i - 1)) - 1}; break;
    }
}
struct seg{
    struct node{
        note a[33];
    }t[maxn << 2 | 1];
    void push_up(int x){
        for(int i = 0; i < m; ++i){
            note p = t[x << 1].a[i];
            int len = i - p.a + p.b;
            t[x].a[i] = p + t[x << 1 | 1].a[len];
        }
    }
    void built(int x, int l, int r){
        if(l == r)return build(t[x].a, cal[l]);
        int mid = (l + r) >> 1;
        built(x << 1, l, mid);
        built(x << 1 | 1, mid + 1, r);
		push_up(x);
    }
    void modify(int x, int l, int r, int pos){
        if(l == r)return build(t[x].a, cal[l]);
        int mid = (l + r) >> 1;
        if(pos <= mid)modify(x << 1, l, mid, pos);
        else modify(x << 1 | 1, mid + 1, r, pos);
        push_up(x);
    }
    note query(int x, int l, int r, int L, int R, int bit){
        if(L <= l && r <= R)return t[x].a[bit];
        int mid = (l + r) >> 1;
        if(R <= mid)return query(x << 1, l, mid, L, R, bit);
        if(L > mid)return query(x << 1 | 1, mid + 1, r, L, R, bit);
        note ans = query(x << 1, l, mid, L, R, bit);
        ans = ans + query(x << 1 | 1, mid + 1, r, L, R, bit - ans.a + ans.b);
        return ans;
    }
}t;
int main(){
	freopen("calculate.in","r",stdin);
//	freopen("calculate.out","w",stdout);
	n = read(), m = read(), q = read();
	scanf("%s",s + 1);
	for(int i = 1; i <= n; ++i)cal[i] = s[i] - '0';	
	t.built(1, 1, n);
	for(int i = 1; i <= q; ++i){
		int opt = read();
		if(opt & 1){
			int l = read(), r = read(), x = read();
			printf("%d\n", t.query(1, 1, n, l, r, __lg(x)).calc(x));
		}else{
			int pos = read(), p = read();
			cal[pos] = p;
            t.modify(1, 1, n, pos);
		}
	}
	return 0;
}

D. 愤怒的小鸟

可反悔贪心

先取 min 转化为取恰好 p,q,r

然后考虑选取a,b,c

a

  1. 直接选最小的

b

  1. b

  2. a, 把之前一个 a 改成 b

c

  1. c

  2. b,改之前的一个 bc

  3. a,改之前的一个 ac

  4. a,改之前的一个 ab ,一个 bc

  5. b, 改之前一个 ba, 一个 ac

八种情况,七个堆

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pli;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 200055;
int n, p, q, r;
int a[maxn], b[maxn], c[maxn];
int vis[maxn];
priority_queue<pli>qcb, qba, qca, qbc;
priority_queue<pli, vector<pli>, greater<pli>>qa, qb, qc;
void make_3star(int x){
	vis[x] = 3;
	qcb.push(pli(c[x] - b[x], x));
	qca.push(pli(c[x] - a[x], x));
}
void make_2star(int x){
	vis[x] = 2;
	qba.push(pli(b[x] - a[x], x));
    qbc.push(pli(b[x] - c[x], x));
}
void make_1star(int x){
	vis[x] = 1;
}
ll get_1star(){
	while(!qa.empty() && vis[qa.top().second])qa.pop();
	return qa.empty() ? 1e18 : qa.top().first;
}
ll get_2star(){
	while(!qb.empty() && vis[qb.top().second])qb.pop();
	return qb.empty() ? 1e18 : qb.top().first;
}
ll get_3star(){
	while(!qc.empty() && vis[qc.top().second])qc.pop();
	return qc.empty() ? 1e18 : qc.top().first;
}
ll make3to2(){
	while(!qcb.empty() && vis[qcb.top().second] != 3)qcb.pop();
	return qcb.empty() ? -1e18 : qcb.top().first;
}
ll make3to1(){
	while(!qca.empty() && vis[qca.top().second] != 3)qca.pop();
	return qca.empty() ? -1e18 : qca.top().first;
}
ll make2to1(){
	while(!qba.empty() && vis[qba.top().second] != 2)qba.pop();
	return qba.empty() ? -1e18 : qba.top().first;
}
ll make2to3(){
    while(!qbc.empty() && vis[qbc.top().second] != 2)qbc.pop();
    return qbc.empty() ? -1e18 : qbc.top().first;
}
ll ans;
int main(){
	freopen("angrybird.in","r",stdin);
	freopen("angrybird.out","w",stdout);
	n = read(), p = read(), q = read(), r = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= n; ++i)b[i] = read();
	for(int i = 1; i <= n; ++i)c[i] = read();
	for(int i = 1; i <= n; ++i)b[i] = min(b[i], c[i]);
	for(int i = 1; i <= n; ++i)a[i] = min(a[i], b[i]);
	for(int i = 1; i <= n; ++i){qa.push(pli(a[i], i)); qb.push(pli(b[i], i)); qc.push(pli(c[i], i));}
	p = p - max(q, r); q = q - r;
	for(int i = 1; i <= r; ++i)make_3star(qc.top().second), ans += qc.top().first, qc.pop();
	for(int i = 1; i <= q; ++i){
		ll v1 = get_2star(), v2 = get_3star() - make3to2();
		if(v1 < v2){
			ans += v1;
			make_2star(qb.top().second);
			qb.pop();
		}else{
			ans += v2;
			int x = qc.top().second, y = qcb.top().second;
			qc.pop(); qcb.pop();
			make_3star(x); make_2star(y);
		}
	}
	for(int i = 1; i <= p; ++i){
		ll v1 = get_1star(), v2 = get_2star() - make2to1(), v3 = get_3star() - make3to1(), v4 = get_3star() - make2to1() - make3to2(), v5 = get_2star() - make3to1() - make2to3();
		if(v1 < v2 && v1 < v3 && v1 < v4 && v1 < v5){
			ans += v1;
			make_1star(qa.top().second);
			qa.pop();
		}else if(v2 < v3 && v2 < v4 && v2 < v5){
			ans += v2;
			int x = qb.top().second, y = qba.top().second;
			qb.pop(); qba.pop();
			make_2star(x); make_1star(y);
		}else if(v3 < v4 && v3 < v5){
			ans += v3;
			int x = qc.top().second, y = qca.top().second;
			qc.pop(); qca.pop();
			make_3star(x); make_1star(y);
		}else if(v4 < v5){
            ans += v4;
            int x1 = qc.top().second, x2 = qba.top().second, x3 = qcb.top().second;
            qc.pop(); qba.pop(); qcb.pop();
            make_3star(x1); make_2star(x3); make_1star(x2);
        }else{
            ans += v5;
            int x1 = qb.top().second, x2 = qca.top().second, x3 = qbc.top().second;
            qb.pop(); qca.pop(); qbc.pop();
            make_3star(x3); make_2star(x1); make_1star(x2);
        }
	}
	printf("%lld\n",ans);
	return 0;
}

posted @   Chen_jr  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示