20241021

Rose_Lu發表於2024-10-21

今天的模擬賽打的比較舒服。
但是還要早起跑操+早讀+升旗就不太好。
去升旗之前做了第一題,簡單的模擬,感覺這很符合cspsT1的難度啊,之前的感覺都有點難了。

  • 【貪吃蛇】
    題意:
    思路:直接用桶記錄蛇的位置,考慮怎麼記錄加和減操作,可以考慮用STL,但是直接維護兩個指標也可以。
    程式碼:
#include <iostream>
#include <cstdio>

using namespace std;
const int N = 110;

int n, m, t, q, x, y, op;
int head, tail = 1, ans;
int a[N][N];
bool b[N][N];
bool flag = 0;
char c;
struct Snake { int x, y; } s[N * N];

void work () {
	if(c == 'U') --x;
	if(c == 'D') ++x;
	if(c == 'L') --y;
	if(c == 'R') ++y;
} 

int main () {
	freopen("snake.in", "r", stdin);
	freopen("snake.out", "w", stdout);
	scanf("%d%d%d%d", &n, &m, &t, &q);
	while(t--) {
		scanf("%d%d", &x, &y);
		b[x][y] = 1;
	}
	scanf("%d%d", &x, &y);
	b[x][y] = 1, s[++head] = {x, y};
	while(q--) {
		++ans;
		scanf("%d", &op);
		if(op == 1) {
			scanf("%s", &c);
			x = s[head].x, y = s[head].y;
			work();
			if(b[x][y] || x < 1 || x > n || y < 1 || y > m) {
				flag = 1; break;
			}
			s[++head] = {x, y}, b[x][y] = 1;
		} else {
			x = s[tail].x, y = s[tail].y;
			b[x][y] = 0;
			++tail;
		}
	}
	if(flag) printf("%d\n", ans);
	else puts("-1");
	return 0;
}
  • 【分糖果】
    題意:參考 皇后遊戲
    思路:考場上沒推出來具有傳遞性的,只推出來 $\min(a_i, b_j) \leq \min(a_j, b_i) $,然後就打上去交了,沒想到過了,應該是資料比較水吧。具體思路可以直接看題解,因為markdown太長了我不想打就不寫了。
    程式碼:
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;
const int N = 2e4 + 10;

int T, n;
ll c[N];
struct zx {
	int x, y, d;
	bool operator < (zx a) const {
		if(a.d != d) return d < a.d;
		if(d <= 0) return x < a.x;
		else return y > a.y;
	}
} a[N];

int main() {
	cin >> T;
	while(T--) {
		cin >> n;
		for(int i = 1; i <= n; ++i) {
			cin >> a[i].x >> a[i].y;
			if(a[i].x == a[i].y) a[i].d = 0;
			if(a[i].x < a[i].y) a[i].d = -1;
			else a[i].d = 1;
		}
		sort(a + 1, a + n + 1);
		ll s = 0;
		for(int i = 1; i <= n; ++i) {
			s += a[i].x;
			c[i] = max(s, c[i - 1]) + a[i].y;
		}
		cout << c[n] << endl;
	}
	return 0;
}
  • 【排序】
    題意:
    思路:考場上沒時間想這道題了,所以就直接寫了個歸併拿了點分,本來預計有50的,結果沒開long long掛了15。正解應該是線段樹。考慮每次操作完之後以被排序過的數為一個數的話它的後面就沒有比他小的了,很顯然,因為排完序了小的都在它前面了。所以每次的排序操作其實就是在原數列上把\(p_j\)之後的大於等於它的數的逆序對值改成零就行了。那就可以考慮維護一下他有沒有被排過序,再維護一個區間最小值來判斷更新是否需要進入這個區間更改是否排序狀態,再維護一個區間逆序對和就行了。
    程式碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define ls (x << 1)
#define rs (x << 1 | 1)

using namespace std;
typedef long long ll;
const int N = 5e5 + 10;
const ll inf = 1e9 + 7;

int n, m, x;
ll a[N], b[N], c[N], ans[N], vis[N];
struct S { ll l, r, s, mn; } t[N << 2];

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

void update (int k) {
    for(int i = k ;i <= n ;i += lowbit(i))
        c[i] += 1;
}

ll sum (int k) {
    ll res = 0;
    for (int i = k; i >= 1 ;i -= lowbit(i))
        res += c[i];
    return res;
}

void pushup (int x) {
	t[x].s = t[ls].s + t[rs].s;
	t[x].mn = min(t[ls].mn, t[rs].mn);
}

void build (int x, int l, int r) {
	t[x].l = l, t[x].r = r;
	if(l == r) {
		t[x].s = ans[l], t[x].mn = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(ls, l, mid), build(rs, mid + 1, r);
	pushup(x);
}

ll modify (int x, int k) {
	if(!t[x].l) return 0;
	int l = t[x].l, r = t[x].r, mid = (l + r) >> 1;
	if(l == r) 
		return t[x].mn;
	if(k <= mid) return modify(ls, k);
	else return modify(rs, k);
}

void change (int x, int L, int R, int k) {
	if(!t[x].l||t[x].mn>k) return;
	int l = t[x].l, r = t[x].r, mid = (l + r) >> 1;
	if(l >= L && r <= R) {
		if(t[x].mn <= k) {
			if(l == r) {
				t[x].mn = inf, t[x].s = 0;
			} else {
				change(ls, L, R, k), change(rs, L, R, k);
				pushup(x);
			}
			
		} else return;
	} else {
		if(L <= mid) change(ls, L, R, k);
		if(R > mid) change(rs, L, R, k);
		pushup(x);
	}
}

int main () {
	freopen("sort.in", "r", stdin);
	freopen("sort.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &a[i]), b[i] = a[i];
    sort(b + 1, b + n + 1);
    int cnt = unique(b + 1, b + 1 + n) - b - 1;
    for (int i = 1; i <= n; ++i)
        a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
    for(int i = n; i >= 1; --i) {
        update(a[i]);
		ans[i] = sum(a[i]) - 1;
    	ans[i] -= vis[a[i]], vis[a[i]]++;
    }
    build(1, 1, n);
    while(m--) {
    	cin >> x;
    	ll sum = modify(1, x);
    	if(sum != inf) 
    		change(1, x, n, sum);
    	printf("%lld\n", t[1].s);
	}
	return 0;
}