标签:ring ret sig font ide 线段树 ble 一个 inline
wzj大佬的模拟赛,蒟蒻又无情爆炸了,我只想弱弱的吐槽一句:这难度为什么是倒着来的啊qwq。。
大意:给出一个n个浮点数(n<=50000)的序列和一个整数k(k<=20),每个点爆炸的概率为a[i](1<=i<=n),每段爆炸的贡献为连续爆炸的长度的k次方,求期望贡献
此题最高分50,写的全是n^2做法,我也不例外,因为正解实在没听懂,暂时留个坑吧,这种题放T1真是满满的槽点,贴个50的
#include <cmath> #include <cstdio> #include <algorithm> using namespace std; #define int long long int n, k; double g[50005], gg[1005][1005]; const int mod=1e6; void reduce(double &x) { int t = (int)(x); x = x - t / mod * mod; } signed main() { scanf("%lld%lld", &n, &k); for(int i = 1; i <= n; i++) scanf("%lf", &g[i]); double ans = 0; for(int i = 1; i <= n; i++) { double now = g[i]; gg[i][i] = g[i]; for(int j = i + 1; j <= n; j++) now = now * g[j], gg[i][j] = now; } for(int i = 1; i <= n; i++) for(int j = 1; j + i - 1 <= n; j++) { double pp = gg[j][j + i - 1]; int l = j, r = j + i - 1; if (l > 1) pp = pp * ((double)(1 - g[l - 1])); if (r < n) pp = pp * ((double)(1 - g[r + 1])); ans = ans + (double)(pp * pow(i, k)); } reduce(ans); printf("%.4lf\n", ans); }
题不难啊,本场比赛码量担当,dfs序+线段树,pushup十分繁琐,以后有机会一定多练(可是时间已经不多了啊)
这是AC人数最多的一题 难度居中
#include <cstdio> #include <algorithm> using namespace std; #define inf 0x3f3f3f3f int n, Q, B[200005], L[200005], ti = 0, pos[200005], id[200005], size[200005]; int tot = 0, Next[200005 << 1], to[200005 << 1], head[200005 << 1]; inline void add(int x, int y) { Next[++tot] = head[x]; to[tot] = y; head[x] = tot; } inline void dfs(int x) { pos[x] = ++ti; id[ti] = x; size[x] = 1; for(int i = head[x]; i; i = Next[i]) { int V = to[i]; dfs(V); size[x] += size[V]; } } struct SegmentTree { int l, r, s, bmx, bcx, bcc, lmx, lcx; }Tree[200005 << 2]; SegmentTree operator +(const SegmentTree &a,const SegmentTree &b) { SegmentTree c; c.l = a.l; c.r = b.r; c.bcx = c.bcc = c.lcx = -inf; c.bmx = max(a.bmx, b.bmx); if (a.bmx > b.bmx) c.s = a.s; else if (a.bmx < b.bmx) c.s = b.s; else if (a.bmx == b.bmx) c.s = a.s + b.s; c.lmx = max(a.lmx, b.lmx); if (a.lmx != c.lmx && a.lmx > c.lcx) c.lcx = a.lmx; if (b.lmx != c.lmx && b.lmx > c.lcx) c.lcx = b.lmx; if (a.lcx != c.lmx && a.lcx > c.lcx) c.lcx = a.lcx; if (b.lcx != c.lmx && b.lcx > c.lcx) c.lcx = b.lcx; if (a.bmx != c.bmx && a.bmx > c.bcx) c.bcx = a.bmx; if (b.bmx != c.bmx && b.bmx > c.bcx) c.bcx = b.bmx; if (a.bcx != c.bmx && a.bcx > c.bcx) c.bcx = a.bcx; if (b.bcx != c.bmx && b.bcx > c.bcx) c.bcx = b.bcx; if (a.bmx != c.bmx && a.bmx != c.bcx && a.bmx > c.bcc) c.bcc = a.bmx; if (a.bcx != c.bmx && a.bcx != c.bcx && a.bcx > c.bcc) c.bcc = a.bcx; if (a.bcc != c.bmx && a.bcc != c.bcc && a.bcc > c.bcc) c.bcc = a.bcc; if (b.bmx != c.bmx && b.bmx != c.bcx && b.bmx > c.bcc) c.bcc = b.bmx; if (b.bcx != c.bmx && b.bcx != c.bcx && b.bcx > c.bcc) c.bcc = b.bcx; if (b.bcc != c.bmx && b.bcc != c.bcc && b.bcc > c.bcc) c.bcc = b.bcc; return c; } inline void build(int l, int r, int x) { Tree[x].l = l; Tree[x].r = r; if (l == r) { Tree[x].s = 1; Tree[x].bmx = B[id[l]]; Tree[x].lmx = L[id[l]]; Tree[x].bcx = -inf; Tree[x].bcc = -inf; Tree[x].lcx = -inf; return; } int mid = (l + r) >> 1; build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1); Tree[x] = Tree[x << 1] + Tree[x << 1 | 1]; return; } inline SegmentTree query(int l, int r, int x) { if (l > r) return (SegmentTree){l, r, -inf, -inf, -inf, -inf, -inf, -inf}; if (l <= Tree[x].l && Tree[x].r <= r) return Tree[x]; int mid = (Tree[x].l + Tree[x].r) >> 1; if (r <= mid) return query(l, r, x << 1); else if (l > mid) return query(l, r, x << 1 | 1); else return query(l, mid, x << 1) + query(mid + 1, r, x << 1 | 1); } int main() { scanf("%d%d", &n, &Q); for(int i = 2, x; i <= n; i++) scanf("%d", &x),add(x, i); for(int i = 1; i <= n; i++) scanf("%d%d", &B[i], &L[i]); dfs(1); build(1, n, 1); for(int i = 1, x; i <= Q; i++) { scanf("%d", &x); int ll = pos[x], rr = pos[x] + size[x] - 1; if (ll == rr){printf("0\n");continue;} SegmentTree Tree1 = query(1, ll - 1, 1) + query(rr + 1, n, 1); SegmentTree Tree2 = query(ll, rr, 1); if (Tree2.s > 1 && Tree1.lmx > 0) printf("%d\n", Tree2.bmx); else if (Tree2.bcx + Tree1.lmx > Tree2.bmx) printf("%d\n", Tree2.bmx); else if (Tree2.bcx + Tree1.lmx < Tree2.bmx) printf("%d\n", max(Tree2.bcx, Tree2.bcx + Tree1.lmx)); else printf("%d\n", max(Tree2.bcx,max((int)(Tree2.bcx + Tree1.lcx), (int)(Tree2.bcc + Tree1.lmx)))); } }
最水的一道,接近Dijkstra模板,考场时唯一需要想想的(判断是否符合条件)出错了 感谢良心数据
这样的放T3,结果我时间没安排好,都没多少时间仔细想,如果再多10分钟这样的题我一定过了qwq
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, m, p, k, w[205], q[205]; int G[205], dis[205][100005]; int tot = 0, Next[20005 << 1], to[20005 << 1], val[20005 << 1], head[20005 << 1], ok[20005 << 1]; bool vis[205][100005]; inline void add(int x,int y,int z, int kk) { Next[++tot] = head[x]; to[tot] = y; val[tot] = z; ok[tot] = kk; head[x] = tot; } struct rec{int x, w, cl;}; inline bool operator <(const rec &a, const rec &b) { return a.w > b.w; } inline int Dijkstra(int s) { priority_queue<rec>q; memset(vis, 0, sizeof vis); memset(dis, 63, sizeof dis); q.push((rec){s, 0, G[s]}); dis[s][G[s]] = 0; int res = -1; while(!q.empty()) { rec tmp = q.top();q.pop(); if (vis[tmp.x][tmp.cl]) continue; vis[tmp.x][tmp.cl] = 1; if (tmp.x == n) if (res == -1) res = tmp.w; else res = min(res, tmp.w); for(int i = head[tmp.x]; i; i = Next[i]) { if ((ok[i] & tmp.cl) == ok[i]) { int V = to[i]; if (dis[V][tmp.cl | G[V]] > (tmp.w + val[i])) dis[V][tmp.cl | G[V]] = tmp.w + val[i], q.push((rec){V, dis[V][tmp.cl | G[V]], tmp.cl | G[V]}); } } } return res; } int main() { memset(G, 0, sizeof G); scanf("%d%d%d%d", &n, &m, &p, &k); for(int i = 1; i <= k; i++) { scanf("%d%d", &w[i], &q[i]); for(int j = 1, x; j <= q[i]; j++) scanf("%d", &x), G[w[i]] |= (1 << (x - 1)); } for(int i = 1, x, y, z, pp; i <= m; i++) { scanf("%d%d%d%d", &x, &y, &z, &pp); int kk = 0; for(int j = 1, xx; j <= pp; j++) { scanf("%d", &xx); kk |= (1 << (xx - 1)); } add(y, x, z, kk); add(x, y, z, kk); } printf("%d\n", Dijkstra(1)); }
标签:ring ret sig font ide 线段树 ble 一个 inline
原文地址:https://www.cnblogs.com/gaojunonly1/p/9484139.html