2019 牛客多校第三场 7/10

本文分享了算法竞赛中的实战经验,包括子串匹配、最小周期计算、笛卡尔树上的分治策略、DP算法的应用,以及如何高效处理大量数据的技巧。文章深入探讨了多种算法的实现细节,并提供了代码示例,适合对算法竞赛感兴趣的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天hdu全程上不去也太惨了,听说福建可以,但是日韩都上不了什么鬼啊。有空复现(((

A

B

对于子串就判一下前缀和,后面那个就是0和1的个数最小值乘2
最开始看错了题,以为是求个数,那如果是求个数的话,子串就SAM上DP,子序列emmmm,只会O(n2)O(n^2)O(n2)的DP

/* ***********************************************
Author        :BPM136
Created Time  :7/25/2019 12:35:15 PM
File Name     :1002.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

int const N = 100005;

int sum[N], cnt[4];
char s[N];
int n;

int main() {
	cin >> n;
	cin >> (s + 1);
	auto mp = map<int, int>();
	for (int i = 1; i <= n; ++i) {
		sum[i] = sum[i - 1] + (s[i] == '0' ? -1 : 1);
		cnt[s[i] - '0']++;
		mp[sum[i]] = -1;
	}
	mp[0] = 0;
	int ans = 0;
	for (int i = 1; i <= n; ++i) 
		if (mp[sum[i]] != -1) 
			ans = max(ans, i - mp[sum[i]]);
		else
			mp[sum[i]] = i;
	cout << ans << ' ' << min(cnt[0], cnt[1]) * 2 << '\n';
    return 0;
}

C

D

求一下最小的d∣φ(p)d|\varphi(p)dφ(p)使得10d=1(mod p)10^d=1(mod \ p)10d=1(mod p)
然后就是算有
∑i=1n∑j=1m[ij==0(mod d)] \sum_{i=1}^n \sum_{j=1}^m [i ^ j == 0(mod \ d)] i=1nj=1m[ij==0(mod d)]
然后我枚举了一下午的iii来算jjj,其实只要枚举jjj来算iii就好啦,当j大的时候答案就是一样的。

#include <iostream>
#include <cstdint>
#include <algorithm>
#include <string>
#include <vector>
#include <iomanip>
#include <cstdio>

using namespace std;

using i64 = int64_t;

int pow_mod (int p, int q, int mod) {
    int ret = 1;
    for (; q; p = (i64)p * p % mod, q >>= 1)
        if (q & 1)
            ret = (i64)ret * p % mod;
    return ret;
}

int min_cycle (int p, int mod) {
    int candi = mod - 1;
    int mn = candi;
    for (int i = 2; i * i <= candi; ++i)
        if (candi % i == 0) {
            if (pow_mod(p, i, mod) == 1)
                return i;
            if (pow_mod(p, candi / i, mod) == 1)
                mn = candi / i;
        }
    return mn;
}

i64 dfs (int *ss, int *sp, i64 mul, int mn, int n, int m) {
    std::cerr << ">" << sp - ss << ' ' << mul << ' ' << mn << ' ' << n << ' ' << m << '\n';
    if (mul > n || mn > m)
        return 0;
    if (ss == sp)
        return m - mn + 1;
    std::cerr << "wtf???\n";

    int p = *ss++;
    int cnt = *ss++;
    i64 ret = 0;
    for (int i = 1; (mul *= p) <= n; ++i)
        ret += dfs(ss, sp, mul, std::max(mn, (cnt + i - 1) / i), n, m);
    return ret;
}

i64 count_bf(int w, int n, int m) {
    i64 cnt = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            if (pow_mod(i, j, w) == 0) 
                ++cnt;
    return cnt;
}

i64 calc(int i, int m, vector<pair<int, int>> const& p) {
	int mi = -1;
	for (auto& tp : p) {
		if (i % tp.first) {
			mi = -1;
			break;
		}
		int tmp = i;
		int ct = 0;
		while (tmp % tp.first == 0) {
			++ct;
			tmp /= tp.first;
		}
		mi = max(mi, (tp.second - 1) / ct);
	}
	if (mi == -1)
		return 0;
	cerr << i << ' ' << mi << '\n';
	return m - mi;
}

i64 count(int w, int n, int m) {
	auto p = vector<pair<int, int>>();
	auto tmp = w;
	for (int i = 2; i * i <= tmp; ++i) 
		if (tmp % i == 0) {
			auto tp = make_pair(i, 0);
			while (tmp % i == 0) {
				++tp.second;
				tmp /= i;
			}
			p.push_back(tp);
		}
	if (tmp > 1)
		p.emplace_back(tmp, 1);
	i64 ret = 0;
	for (int j = 1; j <= min(30, m); ++j) {
		int g = 1;
		for (auto& tp : p) 
			g *= pow_mod(tp.first, (tp.second + j - 1) / j, w);
		ret += n / g;
		if (j == 30) 
			ret += 1LL * n / g * (m - 30);
	}
	return ret;
}

i64 fcount(int w, int n, int m) {
	auto tr = count_bf(w, n, m);
	auto ret = count(w, n, m);
	if (tr != ret)
		cerr << "WA!: " << w << ' ' << n << ' ' << m << ' ' << ret << ' ' << tr << '\n'; 
	return ret;
}

i64 solve (int p, int n, int m) {
    switch (p) {
        case 1:
            return (i64)n * m;
        case 2:
        case 5:
            return 0;
        case 3:
            return (i64)(n / 3) * m;
        default:
            int w = min_cycle(10 % p, p);
            // return (i64)(n / w) * m;
            return fcount(w, n, m);
    }
}

int main () {
    std::ios::sync_with_stdio(false);

	// cout << fcount(96, 100, 101) << '\n';
	int t;
	std::cin >> t;
	while (t--) {
		int p, n, m;
		std::cin >> p >> n >> m;
		std::cout << solve(p, n, m) << '\n';
	}

    return 0;
}

E

F

比赛的时候玩D上头了完全没看F
实际上只要单调栈就好了

/* ***********************************************
Author        :BPM136
Created Time  :7/25/2019 8:35:49 PM
File Name     :1006.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<functional>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define filein(x) freopen(#x".in","r",stdin)
#define fileout(x) freopen(#x".out","w",stdout)
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#define mkd(x) freopen(#x".in","w",stdout);
#define setlargestack(x) int _SIZE=x<<20;char *_PPP=(char*)malloc(_SIZE)+_SIZE;__asm__("movl %0, %%esp\n" :: "r"(_PPP));
#define read2(a,b) read(a),read(b)
#define read3(a,b,c) read(a),read(b),read(c)
#define readg(_x1,_y1,_x2,_y2) read(_x1),read(_y1),read(_x2),read(_y2)
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int  ui;
typedef unsigned long long ull;

namespace fastIO{  
    #define BUF_SIZE 100000  
    #define OUT_SIZE 100000  
    //fread->read  
    bool IOerror=0;  
    inline char nc(){  
		static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;  
		if (p1==pend){  
			p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);  
			if (pend==p1){IOerror=1;return -1;}  
			//{printf("IO error!\n");system("pause");for (;;);exit(0);}  
		}  
		return *p1++;  
	}  
	inline bool blank(char ch){return ch==32||ch==10||ch==13||ch==9;}  
	inline bool enter(char ch){return ch==10||ch==13;}
	inline void read(int &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (sign)x=-x;  
	}  
	inline void read(ll &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (sign)x=-x;  
	}  
	inline void read(double &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (ch==46){  
			double tmp=1; ch=nc();  
			for (;ch>=48&&ch<=57;ch=nc())tmp/=10.0,x+=tmp*(ch-48);  
		}  
		if (sign)x=-x;  
	}  
	inline void read(char *s){  
		char ch=nc();  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;  
		*s=0;  
	}  
	inline void readln(char *s) {
		char ch=nc();
		for (;blank(ch);ch=nc());
		if(IOerror)return;
		for(;!enter(ch)&&!IOerror;ch=nc())*s++=ch;
		*s=0;
	}
	inline void read(char &c){  
		for (c=nc();blank(c);c=nc());  
		if (IOerror){c=-1;return;}  
	} 
#undef OUT_SIZE  
#undef BUF_SIZE  
}
using fastIO::read;

int const N = 505;
int const inf = 1e7;

int a[N][N];
int mi[N], ma[N];

int main() {
	USE_CIN_COUT;
	int T;
	read(T);
	while (T--) {
		int n, m;
		read2(n, m);
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j)
				read(a[i][j]);
				// cin >> a[i][j];
		int ans = 0;
		auto q1 = deque<int>(), q2 = deque<int>();
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j)
				mi[j] = inf, ma[j] = -inf;
			for (int j = i; j <= n; ++j) {
				for (int k = 1; k <= n; ++k) {
					mi[k] = min(mi[k], a[j][k]);
					ma[k] = max(ma[k], a[j][k]);
				}
				int l = 1;
				while (q1.empty() == 0)
					q1.pop_back();
				while (q2.empty() == 0)
					q2.pop_back();

				// cerr << ">> " << i << ' ' << j << " :" << '\n';
				// for (int k = 1; k <= n; ++k)
				//     cerr << mi[k] << ' ';
				// cerr << '\n';
				// for (int k = 1; k <= n; ++k)
				//     cerr << ma[k] << ' ';
				// cerr << '\n';

				for (int r = 1; r <= n; ++r) {
					while (q1.empty() == 0 && ma[q1.back()] <= ma[r])
						q1.pop_back();
					while (q2.empty() == 0 && mi[q2.back()] >= mi[r]) 
						q2.pop_back();
					q1.push_back(r);
					q2.push_back(r);
					// cerr << l << ' ' << r << ' ';
					while (l <= r && ma[q1.front()] - mi[q2.front()] > m) {
						++l;
						if (q1.front() < l)
							q1.pop_front();
						if (q2.front() < l)
							q2.pop_front();
					}
					// cerr << l << ' ' << r << '\n';
					ans = max(ans, (r - l + 1) * (j - i + 1));
				}
			}
		}
		cout << ans << '\n';
	}
    return 0;
}

G

笛卡尔树上分治,每次扫小的那边,二分大的区间算答案

#include <bits/stdc++.h>

using namespace std;

#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()

using ll = long long;

int const N = 300005;
int const LOGN = 20;

int f[N][LOGN];
int rmq_k[N];
int a[N];
ll s[N];
ll ans;
int n;

int get_max_index(int l, int r) {
	int len = r - l + 1;
	int k = rmq_k[len];
	int lidx = f[l][k], ridx = f[r - (1 << k) + 1][k];
	return a[lidx] > a[ridx] ? lidx : ridx;
}

void solve(int l, int r) {
	if (l >= r)
		return;
	if (l + 1 == r) {
		ans += a[l] == a[r];
		return;
	}
	int idx = get_max_index(l, r);
	// cerr << l << ' ' << r << ' ' << idx << '\n';
	solve(l, idx - 1);
	solve(idx + 1, r);
	int mx = a[idx] << 1;
	ll sum = 0;
	if (idx - l > r - idx) {
		for (int i = idx; i <= r; ++i) {
			sum += a[i];
			if (s[i] - s[l - 1] < mx)
				continue;
			int pos = 0;
			if (mx <= sum) 
				pos = idx;
			else {
				pos = lower_bound(s + l, s + idx + 1, s[idx - 1] - mx + sum) - s;
				if (mx - sum == s[idx - 1] - s[pos])
					++pos;
			}
			ans += pos - l + 1;
		}
	} else {
		for (int i = idx; i >= l; --i) {
			sum += a[i];
			if (s[r] - s[i - 1] < mx)
				continue;
			int pos = 0;
			if (mx <= sum)
				pos = idx;
			else
				pos = lower_bound(s + idx, s + r + 1, s[idx] + mx - sum) - s;
			ans += r - pos + 1;
		}
	}
}

int main() {
	ios::sync_with_stdio(0);

	for (int i = 1; i < N; ++i) {
		rmq_k[i] = rmq_k[i - 1];
		if ((1 << (rmq_k[i] + 1)) <= i)
			++rmq_k[i];
	}

	int T;
	cin >> T;
	while (T--) {
		cin >> n;
		for (int i = 1; i <= n; ++i) {
			cin >> a[i];
			f[i][0] = i;
			s[i] = s[i - 1] + a[i];
		}

		for (int j = 1; j < LOGN; ++j)
			for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
				int lidx = f[i][j - 1], ridx = f[i + (1 << (j - 1))][j - 1];
				f[i][j] = a[lidx] > a[ridx] ? lidx : ridx;
				// cerr << i << ' ' << j << ' ' << f[i][j] << '\n';
			}

		ans = 0;
		solve(1, n);
		cout << ans << '\n';
	}
}

H

#include <iostream>
#include <cstdint>
#include <algorithm>
#include <string>
#include <vector>
#include <iomanip>
#include <cstdio>
 
const int INF = 999999999;
 
int main () {
    std::ios::sync_with_stdio(false);
 
    int t;
    std::cin >> t;
    while (t--) {
        int n;
        std::cin >> n;
        auto pts = std::vector<std::pair<int, int>>(n);
        for (auto &pt: pts)
            std::cin >> pt.first >> pt.second;
 
        std::sort(std::begin(pts), std::end(pts));
        auto a = pts[n / 2 - 1];
        auto b = pts[n / 2];
        if (a.first != b.first)
            std::cout << a.first << ' ' << INF << ' ' << b.first << ' ' << -INF << '\n';
        else {
            int l = a.second, r = l + 1;
            int dt = std::min(l - (-INF), INF - r);
            std::cout << a.first - 1 << ' ' << r + dt << ' ' << a.first + 1 << ' ' << l - dt << '\n';
        }
    }
 
    return 0;
}

I

主要是一个结论,如果答案存在,那么值一定可以取前中后三个中位数之一。否则可以调整得到这样的解。
那么我们就可以DP了

#include <bits/stdc++.h>

using namespace std;

int const N = 100005;

int v[N][3];

int f[N][3][3];
int pre[N][3][3];
int a[N];
int n, m;

int getMediam(int x, int y, int z) {
	static int c[3];
	c[0] = x, c[1] = y, c[2] = z;
	sort(c, c + 3);
	return c[1];
}

void dfs(int k, int x, int y) {
	if (k == 2) {
		cout << v[1][x] << ' ' << v[2][y] << ' ';
		return;
	}
	dfs(k - 1, pre[k][x][y], x);
	cout << v[k][y] << ' ';
}

int main() {
	ios::sync_with_stdio(0);
	int T;
	cin >> T;
	while (T--) {
		cin >> n;
		for (int i = 2; i < n; ++i)
			cin >> a[i];
		a[0] = a[1] = a[2];
		a[n] = a[n + 1] = a[n - 1];
		for (int i = 1; i <= n; ++i) {
			for (int j = -1; j <= 1; ++j) 
				v[i][j + 1] = a[i + j];
			sort(v[i], v[i] + 3);
		}
		for (int i = 2; i <= n; ++i) 
			for (int j = 0; j < 3; ++j)
				for (int k = 0; k < 3; ++k)
					f[i][j][k] = i == 2;
		for (int i = 3; i <= n; ++i) 
			for (int j = 0; j < 3; ++j)
				for (int k = 0; k < 3; ++k)
					for (int p = 0; p < 3; ++p) 
						if (f[i - 1][p][k] && getMediam(v[i - 2][p], v[i - 1][k], v[i][j]) == a[i - 1]) {
							f[i][k][j] = 1;
							pre[i][k][j] = p;
						}
		bool flag = 0;
		for (int j = 0; j < 3; ++j) {
			for (int k = 0; k < 3; ++k) 
				if (f[n][j][k]) {
					flag = 1;
					dfs(n, j, k);
					break;
				}
			if (flag)
				break;
		}
		if (flag == 0) 
			cout << -1 << '\n';
		else
			cout << '\n';
	}
}

J

unordered_map内存炸怎么办啊(((
只好写了trie,最后发现自己是傻逼地方写错了,还好过了(
就trie维护name,segment tree维护哪些位置在被使用,复杂度O(nlogn)O(nlogn)O(nlogn)

/* ***********************************************
Author        :BPM136
Created Time  :7/25/2019 2:27:00 PM
File Name     :1010.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<functional>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define filein(x) freopen(#x".in","r",stdin)
#define fileout(x) freopen(#x".out","w",stdout)
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#define mkd(x) freopen(#x".in","w",stdout);
#define setlargestack(x) int _SIZE=x<<20;char *_PPP=(char*)malloc(_SIZE)+_SIZE;__asm__("movl %0, %%esp\n" :: "r"(_PPP));
#define read2(a,b) read(a),read(b)
#define read3(a,b,c) read(a),read(b),read(c)
#define readg(_x1,_y1,_x2,_y2) read(_x1),read(_y1),read(_x2),read(_y2)
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int  ui;
typedef unsigned long long ull;

namespace fastIO{  
    #define BUF_SIZE 100000  
    #define OUT_SIZE 100000  
    //fread->read  
    bool IOerror=0;  
    inline char nc(){  
		static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;  
		if (p1==pend){  
			p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);  
			if (pend==p1){IOerror=1;return -1;}  
			//{printf("IO error!\n");system("pause");for (;;);exit(0);}  
		}  
		return *p1++;  
	}  
	inline bool blank(char ch){return ch==32||ch==10||ch==13||ch==9;}  
	inline bool enter(char ch){return ch==10||ch==13;}
	inline void read(int &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (sign)x=-x;  
	}  
	inline void read(ll &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (sign)x=-x;  
	}  
	inline void read(double &x){  
		bool sign=0; char ch=nc(); x=0;  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		if (ch==45)sign=1,ch=nc();  
		for (;ch>=48&&ch<=57;ch=nc())x=x*10+ch-48;  
		if (ch==46){  
			double tmp=1; ch=nc();  
			for (;ch>=48&&ch<=57;ch=nc())tmp/=10.0,x+=tmp*(ch-48);  
		}  
		if (sign)x=-x;  
	}  
	inline void read(char *s){  
		char ch=nc();  
		for (;blank(ch);ch=nc());  
		if (IOerror)return;  
		for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;  
		*s=0;  
	}  
	inline void readln(char *s) {
		char ch=nc();
		for (;blank(ch);ch=nc());
		if(IOerror)return;
		for(;!enter(ch)&&!IOerror;ch=nc())*s++=ch;
		*s=0;
	}
	inline void read(char &c){  
		for (c=nc();blank(c);c=nc());  
		if (IOerror){c=-1;return;}  
	} 
#undef OUT_SIZE  
#undef BUF_SIZE  
}
using fastIO::read;

int const N = 500005;

int first[N * 10], second[N * 10]; ///val, pos
int ch[N * 10][10];
bool num[N * 10];
int trie_cnt;

inline int trie_newNode() {
	auto& k = trie_cnt;
	++k;
	first[k] = second[k] = num[k] = 0;
	for (int i = 0; i < 10; ++i)
		ch[k][i] = 0;
	return k;
}

void trie_init() {
	trie_cnt = 0;
	trie_newNode();
}

int trie_find(char* c) {
	int p = 1;
	for (int i = 0, len = strlen(c); i < len; ++i)
		p = ch[p][c[i] - '0'];
	if (p && num[p])
		return p;
	return 0;
}

void trie_insert(char* c, int val, int pos) {
	int p = 1;
	for (int i = 0, len = strlen(c); i < len; ++i) {
		if (ch[p][c[i] - '0'] == 0) 
			ch[p][c[i] - '0'] = trie_newNode();
		p = ch[p][c[i] - '0'];
	}
	num[p] = 1;
	first[p] = val;
	second[p] = pos;
}

void trie_delete(char* c) {
	int p = 1;
	for (int i = 0, len = strlen(c); i < len; ++i) 
		p = ch[p][c[i] - '0'];
	num[p] = 0;
	first[p] = second[p] = 0;
}

// unordered_map<string, pair<int, int>> trie; ///val, pos
char dfn[N][12];

int seg_sum[N << 2];

void build(int k, int l, int r) {
	seg_sum[k] = 0;
	if (l == r)
		return;
	int mid = (l + r) >> 1;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
}

void motifiy(int k, int l, int r, int pos, int val) {
	seg_sum[k] += val;
	if (l == r) 
		return;
	int mid = (l + r) >> 1;
	if (pos <= mid)
		motifiy(k << 1, l, mid, pos, val);
	else
		motifiy(k << 1 | 1, mid + 1, r, pos, val);
}

int motifiy_min(int k, int l, int r) {
	seg_sum[k]--;
	if (l == r) 
		return l;
	int mid = (l + r) >> 1;
	if (seg_sum[k << 1]) 
		return motifiy_min(k << 1, l, mid);
	else
		return motifiy_min(k << 1 | 1, mid + 1, r);
}

int get_pos(int k, int l, int r, int kth) {
	if (l == r)
		return l;
	int mid = (l + r) >> 1;
	if (kth <= seg_sum[k << 1])
		return get_pos(k << 1, l, mid, kth);
	else
		return get_pos(k << 1 | 1, mid + 1, r, kth - seg_sum[k << 1]);
}

int get_sum(int k, int l, int r, int ql, int qr) {
	if (ql <= l && r <= qr) 
		return seg_sum[k];
	int ret = 0, mid = (l + r) >> 1;
	if (ql <= mid)
		ret += get_sum(k << 1, l, mid, ql, qr);
	if (qr > mid)
		ret += get_sum(k << 1 | 1, mid + 1, r, ql, qr);
	return ret;
}

int main() {
	USE_CIN_COUT;
	int T;
	read(T);
	int m = 0, sum = 0;
	int opt, v, MAXR, ans, ds;
	static char s[12];
	while (T--) {
		int Q, n;
		read2(Q, n);
		// cin >> Q >> n;
		m = 0, sum = 0;
		MAXR = Q;
		build(1, 1, MAXR);
		trie_init();
		while (Q--) {
			// cin >> opt >> s >> v;
			read3(opt, s, v);
			if (opt == 0) {
				ds = trie_find(s);
				if (ds) {
					auto p = ds;
					ans = first[p];
					motifiy(1, 1, MAXR, second[p], -1);
					second[p] = ++m;
					strcpy(dfn[m], s);
					motifiy(1, 1, MAXR, m, 1);
				} else {
					ans = v;
					trie_insert(s, v, ++m);
					// trie[s] = make_pair(v, ++m);
					strcpy(dfn[m], s);
					motifiy(1, 1, MAXR, m, 1);
					if (sum == n) {
						auto epos = motifiy_min(1, 1, MAXR);
						trie_delete(dfn[epos]);
						// trie.erase(dfn[epos]);
					} else
						++sum;
				}
			} else {
				ds = trie_find(s);
				if (ds == 0) {
					cout << "Invalid" << '\n';
					continue;
				}
				auto pos = get_sum(1, 1, MAXR, 1, second[ds]) + v;
				if (pos <= 0 || pos > sum) {
					cout << "Invalid" << '\n';
					continue;
				}
				auto ts = get_pos(1, 1, MAXR, pos);
				ans = first[trie_find(dfn[ts])];
			}
			cout << ans << '\n';
		}
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值