J
题意:给你一个hash表,让你给出一个字典序最小的输入。
思路:按数字大小从小到大插入,用链表和bit维护过程。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 2e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, tot, all, ans[N], a[N], L[N], R[N]; vector<pii> vec; struct node { int nx, pre, val; } b[N]; struct BIT { int a[N]; void init(int n) { for(int i = 0; i <= n; i++) a[i] = 0; } void modify(int x, int v) { for(int i = x; i <= n; i += i & -i) a[i] += v; } int sum(int x) { int ans = 0; for(int i = x; i; i -= i & -i) ans += a[i]; return ans; } } bit; void del(int u) { int to = b[u].nx; int from = b[u].pre; b[from].nx = b[u].nx; b[to].pre = b[u].pre; } bool is(int l, int r) { if(l == r) return true; if(l < r) return bit.sum(r) - bit.sum(l - 1) == (r - l); return bit.sum(r) + bit.sum(n) - bit.sum(l - 1) == (r + n - l); } void check(int u, int fa) { if(u == fa || b[u].val == -1 || !is(L[u], R[u])) return; int to = b[u].nx; ans[tot++] = b[u].val; bit.modify(u, 1); del(u); check(to, u); } int main() { int T; scanf("%d", &T); while(T--) { tot = 0; all = 0; vec.clear(); scanf("%d", &n); bit.init(n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i].val = -1; b[i].nx = (i + 1 - 1) % n + 1; b[i].pre = (i - 1 - 1 + n) % n + 1; if(a[i] != -1) { L[i] = a[i] % n + 1; R[i] = i; vec.push_back(mk(a[i], i)); } } sort(vec.begin(), vec.end()); for(int i = 0; i < vec.size(); i++) { int l = vec[i].fi % n + 1, r = vec[i].se; b[r].val = vec[i].fi; if(is(l, r)) { check(r, -1); } } if(tot != vec.size()) { puts("-1"); } else { if(tot == 0) { puts(""); } else { printf("%d", ans[0]); for(int i = 1; i < tot; i++) printf(" %d", ans[i]); puts(""); } } } return 0; } /* 1 10 8 10 -1 -1 34 75 86 55 88 18 */
线段树优化建边写法
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> #define pLL pair<long long, long long> #define piii pair<int, pair<int,int>> using namespace std; const int N = 2e5 + 7; const int M = 1e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-10; const double PI = acos(-1); int ans[N], a[N], id[N << 2], idx, sum, tot, n; vector<int> edge[N << 2]; bool f[N << 2]; struct node { int val, deg, id; bool operator < (const node &rhs) const { return val > rhs.val; } } p[N << 2]; void build(int l, int r, int rt) { if(l == r) { id[rt] = l; edge[id[rt]].clear(); p[id[rt]].deg = 0; p[id[rt]].val = a[l]; p[id[rt]].id = l; if(a[l] < 0) f[rt] = true; else f[rt] = false; return; } id[rt] = idx++; edge[id[rt]].clear(); p[id[rt]].deg = 0; p[id[rt]].val = -2; p[id[rt]].id = id[rt]; int mid = l + r >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); edge[id[rt << 1]].push_back(id[rt]); edge[id[rt << 1 | 1]].push_back(id[rt]); p[id[rt]].deg += 2; f[rt] = f[rt << 1] | f[rt << 1 | 1]; } bool addEdge(int L, int R, int to, int l, int r, int rt) { if(l >= L && r <= R) { edge[id[rt]].push_back(to); p[to].deg++; return f[rt]; } int mid = l + r >> 1; bool ans = false; if(L <= mid) ans |= addEdge(L, R, to, l, mid, rt << 1); if(R > mid) ans |= addEdge(L, R, to, mid + 1, r, rt << 1 | 1); return ans; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); idx = n; sum = 0; for(int i = 0; i < n; i++) { scanf("%d", &a[i]); if(a[i] != -1) sum++; } build(0, n - 1, 1); bool judge = false; for(int i = 0; i < n; i++) { if(a[i] == -1) continue; int l = a[i] % n, r = i; if(l < r) { judge |= addEdge(l, r - 1, i, 0, n - 1, 1); } else if(l > r) { if(r) judge |= addEdge(0, r - 1, i, 0, n - 1, 1); judge |= addEdge(l, n - 1, i, 0, n - 1, 1); } if(judge) break; } if(judge) { puts("-1"); } else { priority_queue<node> que; tot = 0; for(int i = 0; i < idx; i++) if(p[i].deg == 0) que.push(p[i]); while(!que.empty()) { node u = que.top(); que.pop(); if(u.val >= 0) ans[tot++] = u.val; for(int i = 0; i < edge[u.id].size(); i++) { int v = edge[u.id][i]; p[v].deg--; if(!p[v].deg) que.push(p[v]); } } if(tot < sum) { puts("-1"); } else { if(!tot) puts(""); else { printf("%d", ans[0]); for(int i = 1; i < tot; i++) printf(" %d", ans[i]); puts(""); } } } } return 0; } /* */
E
题意:这个题意真的是看不懂。。 给你n个点,每个点都有一个出现概率,一个点会覆盖自己左下角的区域,
问你期望的面积是多少。
思路:很容易想到扫描线维护面积并,用线段树维护一下在未被覆盖的概率。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 1e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, hs[N], pos[N], tot; LL x[N], y[N], z[N], f[N], a[N << 2], lazy[N << 2]; LL fastPow(LL a, LL b) { LL ans = 1; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } void build(int l, int r, int rt) { lazy[rt] = 1; if(l == r) { a[rt] = hs[l + 1] - hs[l]; return; } int mid = l + r >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); a[rt] = (a[rt << 1] + a[rt << 1 | 1]) % mod; } void pushdown(int rt) { if(lazy[rt] == 1) return; lazy[rt << 1] = lazy[rt << 1] * lazy[rt] % mod; lazy[rt << 1 | 1] = lazy[rt << 1 | 1] * lazy[rt] % mod; a[rt << 1] = a[rt << 1] * lazy[rt] % mod; a[rt << 1 | 1] = a[rt << 1 | 1] * lazy[rt] % mod; lazy[rt] = 1; } void update(int L, int R, LL v, int l, int r, int rt) { if(l >= L && r <= R) { lazy[rt] = lazy[rt] * v % mod; a[rt] = a[rt] * v % mod; return; } int mid = l + r >> 1; pushdown(rt); if(L <= mid) update(L, R, v, l, mid, rt << 1); if(R > mid) update(L, R, v, mid + 1, r, rt << 1 | 1); a[rt] = (a[rt << 1] + a[rt << 1 | 1]) % mod; } LL query(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return a[rt]; int mid = l + r >> 1; LL ans = 0; pushdown(rt); if(L <= mid) ans = query(L, R, l, mid, rt << 1); if(R > mid) ans = (ans + query(L, R, mid + 1, r, rt << 1 | 1)) % mod; return ans; } struct node { bool operator < (const node &rhs) const { return x < rhs.x; } int x, y; LL p; } qus[N]; int main() { int T; scanf("%d", &T); while(T--) { tot = 0; scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &qus[i].x, &qus[i].y); scanf("%lld%lld", &x[i], &y[i]); f[i] = x[i] * fastPow(y[i], mod - 2) % mod; z[i] = (1 - f[i] + mod) % mod; hs[++tot] = qus[i].y; } hs[++tot] = 0; sort(hs + 1, hs + tot + 1); tot = unique(hs + 1, hs + tot + 1) - hs - 1; hs[tot + 1] = hs[tot]; build(1, tot, 1); for(int i = 1; i <= n; i++) { qus[i].y = lower_bound(hs + 1, hs + tot + 1, qus[i].y) - hs; update(1, qus[i].y - 1, z[i], 1, tot, 1); qus[i].p = fastPow(z[i], mod - 2); } sort(qus + 1, qus + 1 + n); LL ans = 0; qus[0].x = 0; for(int i = 1; i <= n; i++) { LL lenx = qus[i].x - qus[i - 1].x; LL leny = (hs[tot] - a[1] + mod) % mod; ans += lenx * leny % mod; if(ans >= mod) ans -= mod; update(1, qus[i].y - 1, qus[i].p, 1, tot, 1); } printf("%lld\n", ans); } return 0; } /* */
C
数位dp
#include<bits/stdc++.h> #define LL long long #define ll long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 1e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = 1e9 + 7; const int maxn = 1e5; int f[64][128][2], tot; LL n; int s[64]; void add(int &a, int b) { a += b; if(a >= mod) a -= mod; } int dp(int pos, int p, bool fg, int cnt) { if(pos == -1) return p == -1 ? 0 : abs(cnt - 64); if(p != -1 && !fg && f[pos][cnt][p] != -1) return f[pos][cnt][p]; int up = fg ? s[pos] : 1; int ret = 0; for(int i = 0; i <= up; i++) { if(p == -1) { if(!i) add(ret, dp(pos - 1, p, fg && i == up, cnt)); else add(ret, dp(pos - 1, 1, fg && i == up, cnt)); } else { add(ret, dp(pos - 1, i, fg && i == up, cnt + ((i == p) ? -1 : 1))); } } if(p != -1 && !fg) f[pos][cnt][p] = ret; return ret; } int main() { int T; scanf("%d", &T); memset(f, -1, sizeof(f)); while(T--) { scanf("%lld", &n); tot = 0; while(n) { if(n & 1) s[tot++] = 1; else s[tot++] = 0; n >>= 1; } printf("%d\n", dp(tot - 1, -1, 1, 64)); } return 0; } /*\ 10 10 */