2019nc#4
题号 | 标题 | 已通过代码 | 题解 | 通过率 | 团队的状态 |
---|---|---|---|---|---|
A | meeting | 点击查看 | 树直径 | 604/2055 | |
B | xor | 点击查看 | 线段树维护线性基交 | 81/861 | 未通过 |
C | sequence | 点击查看 | 单调栈,笛卡尔树 | 479/2755 | |
D | triples I | 点击查看 | 构造 | 464/2974 | |
E | triples II | 点击查看 | 进入讨论 | 35/84 | 未通过 |
F | merge | 点击查看 | splay,FHQ-TREE | 4/37 | |
G | tree | 点击查看 | 进入讨论 | 2/43 | 未通过 |
H | RNGs | 点击查看 | 进入讨论 | 1/66 | 未通过 |
I | string | 点击查看 | 后缀数组,回文树 | 157/677 | |
J | free | 点击查看 | 分层图最短路 | 784/2790 | |
K | number | 点击查看 | dp | 859/3484 |
K
题意
问一个字符串中有多少个连续子串是300的倍数
思路
O(300n)的dp即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ const int maxn = 1e5+9; ll dp[maxn][303]; char str[maxn]; int main(){ scanf("%s", str + 1); int n = strlen(str + 1); // dp[0][0] = 1; ll ans = 0; for(int i=0; i<n; i++) { int tp = str[i + 1] - '0'; for(int j=0; j<300; j++) { // debug(tp); dp[i+1][(j*10 + tp) % 300] += dp[i][j]; } dp[i+1][tp] ++; ans += dp[i+1][0]; } printf("%lld\n", ans); return 0; }
F merge
题意
给定一个1~n的排列,有两种操作,1)对区间 [le,mid]和[mid+1, ri] 进行一次归并排序,2)查询区间第i个位子上的值。
思路
利用fhq_tree。区间分裂操作。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include <bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ struct fhq_treap { static const int N = 1e5 + 5; struct Node { int val, key, lc, rc, sz, mx; }tree[N]; int rt, tot; inline void init() { rt = tot = 0; tree[rt].sz = tree[rt].val = tree[rt].lc = tree[rt].rc = 0; srand(time(0)); } inline void update(int rt) { tree[rt].sz = tree[tree[rt].lc].sz + 1 + tree[tree[rt].rc].sz; tree[rt].mx = max(tree[tree[rt].lc].mx,max(tree[rt].val,tree[tree[rt].rc].mx)); } void split_val(int rt, int &a, int &b, int val) { if(rt == 0) {a = b = 0; return ;} if(max(tree[rt].val , tree[tree[rt].lc].mx) <= val) { a = rt; split_val(tree[rt].rc, tree[a].rc, b, val); } else { b = rt; split_val(tree[rt].lc, a, tree[b].lc, val); } update(rt); } void split_sz(int rt, int &a, int &b, int sz) { if(rt == 0) {a = b = 0; return ;} if(tree[tree[rt].lc].sz + 1 > sz) { b = rt; split_sz(tree[rt].lc, a, tree[b].lc, sz); } else { a = rt; split_sz(tree[rt].rc, tree[a].rc, b, sz - 1 - tree[tree[rt].lc].sz); } update(rt); } void merge(int &rt, int a, int b) { if(a==0 || b==0) { rt = a+b; return ; } if(tree[a].key < tree[b].key) { rt = a; merge(tree[rt].rc, tree[a].rc, b); } else { rt = b; merge(tree[rt].lc, a, tree[b].lc); } update(rt); } inline int new_node(int val) { tree[++tot].sz = 1; tree[tot].val = val; tree[tot].lc = tree[tot].rc = 0; tree[tot].key = rand(); tree[tot].mx = val; return tot; } void ins(int &rt, int val) { int x = 0, y = 0, node = new_node(val); merge(rt, rt, node); } void delete_node(int &rt, int val) { int x = 0, y = 0, z = 0; split_val(rt, x, y, val); split_val(x, x, z, val-1); merge(z, tree[z].lc, tree[z].rc); merge(x, x, z); merge(rt, x, y); } inline int get_kth(int rt, int k) { while(tree[tree[rt].lc].sz+1 != k) { if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc; else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc; } return tree[rt].val; } int get_rnk(int &rt, int val) { int x = 0, y = 0; split_val(rt, x, y, val-1); int tmp = tree[x].sz+1; merge(rt, x, y); return tmp; } int get_pre(int &rt, int val) { int x = 0, y = 0; split_val(rt, x, y, val-1); int tmp = get_kth(x, tree[x].sz); merge(rt, x, y); return tmp; } int get_scc(int &rt, int val) { int x = 0, y = 0; split_val(rt, x, y, val); int tmp = get_kth(y, 1); merge(rt, x, y); return tmp; } }t; const int maxn = 1e5+9; int n,m; int a[maxn]; void display(int x) { if(t.tree[x].lc) display(t.tree[x].lc); if(t.tree[x].rc) display(t.tree[x].rc); } void solve(int le, int mid ,int ri) { int x, y, z; t.split_sz(t.rt, x, z, ri); t.split_sz(x, x, y, mid); int tmp; int r = 0; while(x && y) { int p = t.get_kth(x, 1); int q = t.get_kth(y, 1); if(p > q) swap(p, q), swap(x, y); t.split_val(x, tmp, x, q); t.merge(r,r, tmp); } t.merge(r, r, x); t.merge(r, r, y); t.merge(r, r, z); t.rt = r; } int main(){ t.init(); scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); t.ins(t.rt, a[i]); } while(m--){ int op; scanf("%d", &op); if(op == 2) { int x; scanf("%d", &x); printf("%d\n", t.get_kth(t.rt, x)); } else { int le, mid, ri; scanf("%d%d%d", &le, &mid, &ri); solve(le, mid, ri); } } return 0; } /* 5 10 3 2 1 5 4 1 1 2 5 */
skr