LOJ刷题记录:2012-2017(SCOI2016)
来源:互联网 发布:淘宝头像设计制作 编辑:程序博客网 时间:2024/06/07 12:13
LOJ刷题记录:2012-2017(SCOI2016)
loj#2012. 「SCOI2016」背单词
神贪心…
所有串翻转,考虑建一棵这样的树,
#include <bits/stdc++.h>using namespace std;const int MAXN = 600005;int chl[MAXN][26], top = 0, root = 0;int fin[MAXN];void push(int &nd, const char *str){ if (!nd) nd = ++top; if (*str == '\0') fin[nd] = 1; else push(chl[nd][*str-'a'], str+1);}int n;char str[MAXN];vector<int> v[MAXN];int siz[MAXN];int dfn[MAXN], dfn_top = 0;long long ans = 0;void dfs_build(int nd, int last){ if (last && fin[nd]) v[last].push_back(nd), last = nd; if (!last) last = nd; for (int i = 0; i < 26; i++) if (chl[nd][i]) dfs_build(chl[nd][i], last);}void dfs_siz(int nd){ siz[nd] = 1; for (auto i : v[nd]) { dfs_siz(i); siz[nd] += siz[i]; }}bool cmp(int i, int j){ return siz[i] < siz[j]; }void calc(int nd, int f){ dfn[nd] = ++dfn_top; if (nd != root) ans += dfn[nd]-dfn[f]; sort(v[nd].begin(), v[nd].end(), cmp); for (auto i : v[nd]) calc(i, nd);}int main(){ scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", str); int L = strlen(str); reverse(str, str+L); push(root, str); } fin[root] = 1; dfs_build(root, 0); dfs_siz(root); calc(root, 0); printf("%lld\n", ans); return 0;}
loj#2013. 「SCOI2016」幸运数字
小清新数据结构~
原来是用的树剖-线性基三个
#include <bits/stdc++.h>using namespace std;const int MAXN = 20005, MAXQ = 200005;struct linear_base { long long k[70]; int top = 0; inline void clear() { top = 0; } void push(long long x) { for (int i = 1; i <= top; i++) if ((x^k[i]) < x) x ^= k[i]; if (!x) return; for (int i = 1; i <= top; i++) if ((x^k[i]) < k[i]) k[i] ^= x; k[++top] = x; for (int i = top; i > 1 && k[i] > k[i-1]; i--) swap(k[i], k[i-1]); } long long get_max() { long long ans = 0; for (int i = 1; i <= top; i++) if ((ans^k[i])>ans) ans ^= k[i]; return ans; } friend linear_base operator + (const linear_base &a, long long b) { linear_base c = a; c.push(b); return c; } friend linear_base operator + (const linear_base &a, const linear_base &b) { linear_base c = a; for (int i = 1; i <= b.top; i++) c.push(b.k[i]); return c; }};struct node { int to, next;} edge[MAXN*2];int head[MAXN], top = 0;void push(int i, int j){ edge[++top] = (node) {j, head[i]}, head[i] = top; }int vis[MAXN], siz[MAXN], col[MAXN];long long ans[MAXN*10];long long d[MAXN];linear_base lb[MAXN];int n, q;void dfs_siz(int nd, int f){ siz[nd] = 1; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f || vis[to]) continue; dfs_siz(to, nd), siz[nd] += siz[to]; }}void dfs_find_center(int nd, int f, const int totsiz, int &ans, int &max_siz){ int cnt = (f!=0)*(totsiz-siz[nd]); for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f || vis[to]) continue; dfs_find_center(to, nd, totsiz, ans, max_siz); cnt = max(cnt, siz[to]); } if (cnt < max_siz) ans = nd, max_siz = cnt;}void dfs_paint(int nd, int f, int c){ col[nd] = c; lb[nd] = lb[f]+d[nd]; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f || vis[to]) continue; dfs_paint(to, nd, c); }}vector<pair<int, int> > qy[MAXN];int tp = 0;int tmp = 0;void dfs_calc(int nd, int f){ for (auto i : qy[nd]) if (col[i.first] > tmp && col[i.first] < col[nd]) ans[i.second] = (lb[i.first]+lb[nd]).get_max(); for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; if (to == f || vis[to]) continue; dfs_calc(to, nd); }}void calc(int nd){ dfs_siz(nd, 0); int center = nd, tt = INT_MAX; dfs_find_center(nd, 0, siz[nd], center, tt), vis[center] = 1; tmp = tp; lb[center].clear(), lb[center].push(d[center]); // cerr << center << endl; for (int i = head[center]; i; i = edge[i].next) { int to = edge[i].to; if (vis[to]) continue; dfs_paint(to, center, ++tp); } for (auto i : qy[center]) if (col[i.first] > tmp) { ans[i.second] = lb[i.first].get_max(); } for (int i = head[center]; i; i = edge[i].next) { int to = edge[i].to; dfs_calc(to, center); } for (int i = head[center]; i; i = edge[i].next) { int to = edge[i].to; if (!vis[to]) calc(to); }}int main(){ scanf("%d%d", &n, &q); for (int i = 1; i <= n; i++) scanf("%lld", &d[i]); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); push(u, v), push(v, u); } for (int i = 1; i <= q; i++) { int x, y; scanf("%d%d", &x, &y); if (x == y) ans[i] = d[x]; else qy[x].push_back(make_pair(y, i)), qy[y].push_back(make_pair(x, i)); } calc(1); for (int i = 1; i <= q; i++) printf("%lld\n", ans[i]); return 0;}
loj#2014. 「SCOI2016」萌萌哒
真-神数据结构系列…..
和花神游历各国是一类题…本质有用的操作只有很少(这道题是
这个题的方法是你用ST表的思路,将
#include <bits/stdc++.h>using namespace std;const int MAXN = 100005;int n, q;pair<int,int> f[MAXN][20];pair<int,int> findf(const pair<int,int> &pr){ return f[pr.first][pr.second]!=pr?f[pr.first][pr.second]=findf(f[pr.first][pr.second]):pr; }const int mod = 1e9+7;void link(const pair<int,int> &a, const pair<int,int> &b){ // cerr << a.first << " " << a.second << "," << b.first << " " << b.second << endl; pair<int,int> fa = findf(a), fb = findf(b); if (fa == fb) return; f[fa.first][fa.second] = fb; if (a.second != 0) { link(make_pair(a.first, a.second-1), make_pair(b.first, b.second-1)); link(make_pair(a.first+(1<<(a.second-1)), a.second-1), make_pair(b.first+(1<<(b.second-1)), b.second-1)); }}int main(){ scanf("%d%d", &n, &q); int l1, l2, r1, r2; for (int i = 1; i <= n; i++) for (int j = 0; j < 20; j++) f[i][j] = make_pair(i, j); for (int i = 1; i <= q; i++) { scanf("%d%d%d%d", &l1, &r1, &l2, &r2); int d = r1-l1+1; for (register int j = 0; j < 20; j++) if (d&(1<<j)) { link(make_pair(l1, j), make_pair(l2, j)); l1 += (1<<j), l2 += (1<<j); } } int ans = 1; for (int i = 1; i <= n; i++) if (f[i][0] == make_pair(i, 0)) { if (findf(make_pair(1, 0)) == f[i][0]) ans = (long long)ans*9%mod; else ans = (long long)ans*10%mod; } printf("%d\n", ans); return 0;}
loj#2015. 「SCOI2016」妖怪
一眼题…设
但是这样会被卡时间…然后发现有几个数据都是递增的,可能到最后才能发现冲突…random_shullfe了一下就过了…以后要养成random_shuffle的好习惯…
大家貌似是三分的…?按照codeforces那个题的经验三分可能有点问题吧..
#include <bits/stdc++.h>using namespace std;const int MAXN = 1000005;int n;struct p { double a, b; friend bool operator < (const p &a, const p &b) { return a.a<b.a||(a.a==b.a&&a.b<b.b); }} pt[MAXN];double L = 0, R = 1e10;bool judge(double k){ L = 0, R = 1e10; register double w, dt; for (register int i = 1; i <= n; i++) { w = k-pt[i].a-pt[i].b, dt = sqrt(w*w-4*pt[i].a*pt[i].b); L = max((w-dt)/(2*pt[i].b), L), R = min((w+dt)/(2*pt[i].b), R); if (L >= R) return 0; } return 1;}int main(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lf%lf", &pt[i].a, &pt[i].b); //sort(pt+1, pt+n+1); srand(time(0)); random_shuffle(pt+1, pt+n+1); double l = 0, r = 1.5e8, mid; for (int i = 1; i <= n; i++) l = max(l, pt[i].a+pt[i].b+2*sqrt(pt[i].a*pt[i].b)); while (r-l >= 1e-6) { mid = (l+r)/2; if (judge(mid)) r = mid; else l = mid; } printf("%.4f\n", l); return 0;}
loj#2016. 「SCOI2016」美味
新套路get√…
其实那个异或只不过是改变了每一位0/1的优先级而已..所以按照新的优先级二分(其实就是逐位确定)然后用主席树统计一下答案…
#include <bits/stdc++.h>using namespace std;const int MAXN = 200005;int n, m;int a[MAXN];int sum[MAXN*40], l[MAXN*40], r[MAXN*40], lc[MAXN*40], rc[MAXN*40], top = 0, root[MAXN];void build(int &nd, int opl, int opr){ nd = ++top, l[nd] = opl, r[nd] = opr; if (opl < opr) build(lc[nd], opl, (opl+opr)/2), build(rc[nd], (opl+opr)/2+1, opr);}void modify(int pre, int &nd, int pos, int dt){ nd = ++top, l[nd] = l[pre], r[nd] = r[pre], sum[nd] = sum[pre]+dt; if (l[nd] < r[nd]) { int mid = (l[nd]+r[nd])/2; if (pos <= mid) rc[nd] = rc[pre], modify(lc[pre], lc[nd], pos, dt); else lc[nd] = lc[pre], modify(rc[pre], rc[nd], pos, dt); }}int query(int nd, int opl, int opr){ // cerr << opl << " " << opr << " " << l[nd] << " " << r[nd] << endl; if (opl > opr) return 0; if (l[nd] == opl && r[nd] == opr) return sum[nd]; else { int mid = (l[nd]+r[nd])/2; if (opr <= mid) return query(lc[nd], opl, opr); else if (opl > mid) return query(rc[nd], opl, opr); else return query(lc[nd], opl, mid)+query(rc[nd], mid+1, opr); }}int query_sum(int L, int R, int opl, int opr){ // cerr << opl << " " << opr << endl; return query(root[R], opl, opr)-query(root[L-1], opl, opr);}int main(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(root[0], 1, n); for (int i = 1; i <= n; i++) modify(root[i-1], root[i], a[i], 1); cerr << query_sum(1, 3, 2, 4) << endl; for (int i = 1; i <= m; i++) { int b, x, opl, opr, cur = 0; scanf("%d%d%d%d", &b, &x, &opl, &opr); for (int j = 20; j >= 0; j--) { int pos = ((b&(1<<j))==0); if (query_sum(opl, opr, max(1, (cur|(pos<<j))-x), min((cur|(pos<<j)|((1<<j)-1))-x, n)) > 0) { cur |= pos<<j; } else cur |= (!pos)<<j; } printf("%d\n", cur^b); } return 0;}
loj#2017. 「SCOI2016」围棋
轮廓线dp….坑待填
阅读全文
0 0
- LOJ刷题记录:2012-2017(SCOI2016)
- LOJ刷题记录:2000-2005(SDOI2017)
- LOJ刷题记录:2006-2011(SCOI2015)
- LOJ刷题记录:2018-2020
- LOJ刷题记录:SHOI2016(2036-2041)
- LOJ刷题记录:2024-2029(SHOI2016)
- LOJ刷题记录:2030-2035(SDOI2016)
- 杭电题库刷题记录2012
- OI刷题记录
- OI刷题记录~
- leetcode刷题记录
- 刷题记录
- 6.22刷题记录
- 7.26-刷题记录
- hdu 刷题记录
- 面试刷题记录
- 每日刷题记录
- leetcode刷题记录
- XML解析原理 | QiuRiMangCao
- LOJ刷题记录:2006-2011(SCOI2015)
- Qt之模型/视图(实时更新数据)
- Maven本地仓库配置及修改Maven的本地仓库路径
- HDU_6060 RXD and dividing 【DFS】
- LOJ刷题记录:2012-2017(SCOI2016)
- Qt之模型/视图(自定义风格)
- Focal Loss
- 在Windows 系统安装基于Python3.5 版本的Matplotlib库
- 织梦dedecms让dede:channel支持调用[field:seotitle/]
- 不重复数字求和
- 层级问题,z-index的使用说明
- C++读取特定路径下文件目录及文件名称
- spring详解:使用注解方式注入属性