bupt summer training for 16 #5 ——数据结构
https://vjudge.net/contest/173780
A.假设 Pt = i,则由Ppi = i得
Ppt = t = Pi
所以就有 if Pt = i then Pi = t
#include <cstdio>
#include <algorithm> using namespace std; int n, a[]; int main() {
scanf("%d", &n);
if(n & ) puts("-1");
else {
for(int i = ;i <= n;i ++)
a[i] = i;
for(int i = ;i <= n;i += )
swap(a[i], a[i + ]);
for(int i = ;i <= n;i ++)
printf("%d ", a[i]);
}
}
B.
C.treap练手题,STL_set练手题,链表练手题
set用的不熟所以直接上的链表
排序后时间倒序来看的思路
#include <cstdio>
#include <algorithm> using namespace std; typedef long long ll; const int maxn = ; int n, b[maxn]; ll ans; struct List{
int next, last;
}c[maxn]; struct node{
ll x;
int y;
bool operator < (const node &a) const {
return x < a.x;
}
}a[maxn]; int main() {
scanf("%d", &n);
for(int i = ;i <= n;i ++)
scanf("%lld", &a[i].x), a[i].y = i;
ans = a[].x;
a[].x = -1000000000000ll;
a[n + ].x = 1000000000000ll;
sort(a + , a + n + );
for(int i = ;i <= n;i ++) b[a[i].y] = i;
for(int i = ;i <= n;i ++) {
c[i].next = i + ;
c[i].last = i - ;
}
for(int i = n;i > ;i --) {
ans += min(a[b[i]].x - a[c[b[i]].last].x, a[c[b[i]].next].x - a[b[i]].x);
c[c[b[i]].last].next = c[b[i]].next;
c[c[b[i]].next].last = c[b[i]].last;
}
printf("%lld\n", ans);
return ;
}
D.边权给点,点修改和路径查询
直接上树剖+线段树,考场写狗
多组数据需要clear存边的vector,fa 和 son
修改的时候bel[i]找到第 i 条边权给的点
还要对应该点在线段树上的叶节点位置!
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std; const int maxn = ; int Case, n, M; struct Edge{
int v, w, num;
}; vector <Edge> edge[maxn]; char str[]; int a, b, tr[maxn << ]; int bel[maxn], siz[maxn], son[maxn], val[maxn]; int cnt, fa[maxn], dep[maxn], pos[maxn], dfn[maxn], top[maxn]; void dfs1(int u) {
siz[u] = ;
for(int v, i = ;i < edge[u].size();i ++) {
v = edge[u][i].v;
if(v == fa[u]) continue;
fa[v] = u;
dep[v] = dep[u] + ;
val[v] = edge[u][i].w;
bel[edge[u][i].num] = v;
dfs1(v), siz[u] += siz[v];
if(siz[son[u]] < siz[v]) son[u] = v;
}
} void dfs2(int u, int tp) {
top[u] = tp, pos[u] = ++ cnt, dfn[cnt] = u;
if(son[u]) dfs2(son[u], tp);
for(int v, i = ;i < edge[u].size();i ++) {
v = edge[u][i].v;
if(v != fa[u] && v != son[u])
dfs2(v, v);
}
} void change(int i, int x) {
i = pos[i];
for(tr[i += M] = x, i >>= ;i;i >>= )
tr[i] = max(tr[i << ], tr[i << | ]);
} int mmax(int s, int t) {
int res = -;
for(s += M - , t += M + ;s ^ t ^ ;s >>= , t >>= ) {
if(~ s & ) res = max(res, tr[s ^ ]);
if( t & ) res = max(res, tr[t ^ ]);
}
return res;
} void query(int u, int v) {
int fu = top[u], fv = top[v], res = -;
while(fu != fv) {
if(dep[fu] < dep[fv]) swap(u, v), swap(fu, fv);
res = max(res, mmax(pos[fu], pos[u]));
u = fa[fu], fu = top[u];
}
if(u == v) printf("%d\n", res);
else {
if(dep[u] < dep[v]) swap(u, v);
printf("%d\n", max(res, mmax(pos[v] + , pos[u])));
}
} int main() {
//freopen("test.txt","r",stdin);
val[] = -;
int u, v, w;
scanf("%d", &Case);
while(Case --) {
cnt = ;
scanf("%d", &n);
for(int i = ;i <= n;i ++) edge[i].clear(), fa[i] = son[i] = ;
for(int i = ;i < n;i ++) {
scanf("%d %d %d", &u, &v, &w);
edge[u].push_back((Edge){v, w, i});
edge[v].push_back((Edge){u, w, i});
}
dfs1(), dfs2(, );
for(M = ;M < n + ; M <<= );
for(int i = ;i <= n;i ++) tr[i + M] = val[dfn[i]];
for(int i = n + ;i <= M + ;i ++) tr[i + M] = val[];
for(int i = M;i;i --) tr[i] = max(tr[i << ], tr[i << | ]);
while(scanf("%s", str), str[] != 'D') {
if(str[] == 'C') scanf("%d %d", &a, &b), change(bel[a], b);
else scanf("%d %d", &a, &b), query(a, b);
}
puts("");
}
}
E.考场上脑补出来一个正解,可惜只差了一步
两个单调队列,一增一减,从前向后扫
当扫到某个位置,最大差距 > R 时
踢出两个队列中位置最靠前的元素直至差距 <= R
如果这是最大差距 >= L 则更新答案即可
时间复杂度O(n),别人说这是个做过的RMQ啊...
#include <cstdio>
#include <algorithm> using namespace std; const int maxn = ; int n, x, y, m, a[maxn], q1[maxn], q2[maxn]; int l1, r1, l2, r2, t; int main() {
while(scanf("%d %d %d", &n, &x, &y) != EOF) {
for(int i = ;i <= n;i ++)
scanf("%d", &a[i]);
m = t = , l1 = l2 = , r1 = r2 = ;
for(int i = ;i <= n;i ++) {
while(l1 <= r1 && a[i] > a[q1[r1]]) r1 --;
q1[++ r1] = i;
while(l2 <= r2 && a[i] < a[q2[r2]]) r2 --;
q2[++ r2] = i;
while(l1 <= r1 && l2 <= r2 && a[q1[l1]] > a[q2[l2]] + y) {
if(q1[l1] < q2[l2]) t = q1[l1 ++];
else t = q2[l2 ++];
}
if(l1 <= r1 && l2 <= r2 && a[q1[l1]] >= a[q2[l2]] + x) m = max(m, i - t);
}
printf("%d\n", m);
}
return ;
}
F.就是枚举min,然后单调队列求出左右拓展多远就好了
#include <cstdio> const int maxn = ; int l = , r, q[maxn]; int L, R, n, a[maxn], b[maxn], c[maxn]; long long ans = -, tmp, s[maxn]; int main() {
scanf("%d", &n);
for(int i = ;i <= n;i ++)
scanf("%d", &a[i]), s[i] = a[i] + s[i - ];
for(int i = ;i <= n;i ++) {
while(l <= r && a[i] < a[q[r]]) b[q[r]] = i - q[r], r --;
q[++ r] = i;
}
while(l <= r) b[q[r]] = n + - q[r], r --;
l = , r = ;
for(int i = n;i;i --) {
while(l <= r && a[i] < a[q[r]]) c[q[r]] = q[r] - i, r --;
q[++ r] = i;
}
while(l <= r) c[q[r]] = q[r], r --;
for(int i = ;i <= n;i ++) {
tmp = (s[i + b[i] - ] - s[i - c[i]]) * a[i];
if(tmp > ans) ans = tmp, L = i - c[i] + , R = i + b[i] - ;
}
printf("%lld\n%d %d", ans, L ,R);
return ;
}
G.开始没看清题发现大家都会写区间众数?
连续的相同...线段树傻逼题
#include <cstdio>
#include <algorithm> using namespace std; const int maxn = ; struct node{
int ls, rs, lc, rc, mm;
}tr[maxn << ]; int n, m, c[maxn]; node operator +(const node &a, const node &b) {
node res;
res.ls = a.ls;
res.lc = a.lc;
res.rs = b.rs;
res.rc = b.rc;
res.mm = max(a.mm, b.mm);
if(a.rc == b.lc) {
res.mm = max(res.mm, a.rs + b.ls);
if(a.lc == a.rc) res.ls += b.ls;
if(b.lc == b.rc) res.rs += a.rs;
}
return res;
} void build(int o, int l, int r) {
if(l == r) {
tr[o] = (node){, , c[r], c[r], };
return;
}
int mid = (l + r) >> ;
build(o << , l, mid);
build(o << | , mid + , r);
tr[o] = tr[o << ] + tr[o << | ];
} node ask(int o, int l, int r, int s, int t){
if(s <= l && r <= t) return tr[o];
int mid = (l + r) >> ;
if(t <= mid) return ask(o << , l, mid, s, t);
else if(s > mid) return ask(o << | , mid + , r, s, t);
else return ask(o << , l, mid, s, t) + ask(o << | , mid + , r, s, t);
} int main() {
int a, b;
while(scanf("%d %d", &n, &m), n != ) {
for(int i = ;i <= n;i ++)
scanf("%d", &c[i]);
build(, , n);
//printf("%d %d %d\n",tr[1].mm,tr[6].rc, tr[7].lc);
while(m --) {
scanf("%d %d", &a, &b);
printf("%d\n", ask(, , n, a, b).mm);
}
}
}
H.
I.无修改查询树上路径和,随便做啦
dis[u] + dis[v] - dis[lca] * 2
我直接上的bfs树剖求lca
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std; const int maxn = ; struct Edge{
int v, w;
}; vector <Edge> edge[maxn]; int Case, n, m, a, b, c, dis[maxn]; int l, r, q[maxn], siz[maxn], son[maxn]; int cnt, fa[maxn], dep[maxn], top[maxn]; int lca(int u, int v) {
int fu = top[u], fv = top[v];
while(fu != fv) {
if(dep[fu] < dep[fv]) swap(u, v), swap(fu, fv);
u = fa[fu], fu = top[u];
}
return dep[u] < dep[v] ? u : v;
} int main() {
int u, v, w;
scanf("%d", &Case);
while(Case --) {
scanf("%d %d", &n, &m);
for(int i = ;i < n;i ++) {
scanf("%d %d %d", &u, &v, &w);
edge[u].push_back((Edge){v, w});
edge[v].push_back((Edge){u, w});
}
l = r = , q[++ r] = ;
while(l <= r) {
u = q[l ++];
siz[u] = , son[u] = top[u] = ;
for(int i = ;i < edge[u].size();i ++) {
v = edge[u][i].v;
if(v == fa[u]) continue;
fa[v] = u, q[++ r] = v, dep[v] = dep[u] + , dis[v] = dis[u] + edge[u][i].w;
}
}
for(int i = n;i > ;i --) {
siz[fa[q[i]]] += siz[q[i]];
if(!son[fa[q[i]]] || siz[son[fa[q[i]]]] < siz[q[i]]) son[fa[q[i]]] = q[i];
}
for(int i = ;i <= n;i ++) {
u = q[i];
if(son[fa[u]] == u) top[u] = top[fa[u]];
else top[u] = u;
}
while(m --) {
scanf("%d %d", &a, &b);
c = lca(a, b);
printf("%d\n", dis[a] - dis[c] - dis[c] + dis[b]);
}
}
}
J.裸树状数组
#include <cstdio> const int maxn = ; int c[maxn], a[maxn]; int Case, n, x, y; char str[]; int lowbit(int x) {
return (x & (-x));
} int ask(int i) {
int res = ;
while(i > ) res += c[i], i -= lowbit(i);
return res;
} void add(int i, int x) {
while(i <= n) c[i] += x, i += lowbit(i);
} int main() {
//freopen("test.txt", "r", stdin);
scanf("%d", &Case);
for(int tt = ;tt <= Case;tt ++) {
printf("Case %d:\n", tt);
scanf("%d", &n);
for(int i = ;i <= n;i ++)
scanf("%d", &a[i]), a[i] += a[i - ];
while(scanf("%s", str), str[] != 'E') {
scanf("%d %d", &x, &y);
if(str[] == 'Q') printf("%d\n", ask(y) - ask(x - ) + a[y] - a[x - ]);
else add(x, y * (str[] == 'A' ? : -));
}
for(int i = ;i <= n;i ++) c[i] = ;
}
return ;
}
K.区间加和区间求和,差分树状数组除非有封装好的板子
不然现场还是只能写线段树
#include <cstdio>
#include <algorithm> using namespace std; typedef long long ll; const int maxn = ; int n, m, d[maxn]; char str[]; int a, b, c; ll s[maxn]; struct node{
ll lazy, sum;
}tr[maxn << ]; void pushup(int o) {
tr[o].sum = tr[o << ].sum + tr[o << | ].sum;
} void pushdown(int o, int l, int r) {
if(!tr[o].lazy) return;
int mid = (l + r) >> ;
tr[o << ].sum += tr[o].lazy * (mid - l + );
tr[o << | ].sum += tr[o].lazy * (r - mid);
tr[o << ].lazy += tr[o].lazy;
tr[o << |].lazy += tr[o].lazy;
tr[o].lazy = ;
} void add(int o, int l, int r, int s, int t, int x) {
if(l != r) pushdown(o, l, r);
if(s <= l && r <= t) {
tr[o].lazy += x;
tr[o].sum += 1ll * x * (r - l + );
return;
}
int mid = (l + r) >> ;
if(s <= mid) add(o << , l, mid, s, t, x);
if(mid < t) add(o << | , mid + , r, s, t, x);
pushup(o);
} ll query(int o, int l, int r, int s, int t) {
if(l != r) pushdown(o, l, r);
if(s <= l && r <= t) return tr[o].sum;
ll res = ;
int mid = (l + r) >> ;
if(s <= mid) res += query(o << , l, mid, s, t);
if(mid < t) res += query(o << | , mid + , r, s, t);
pushup(o);
return res;
} int main(int argc, char const *argv[]){
scanf("%d %d", &n, &m);
for(int i = ;i <= n;i ++)
scanf("%d", &d[i]), s[i] = s[i - ] + d[i];
while(m --) {
scanf("%s %d %d", str, &a, &b);
if(str[] == 'Q') printf("%lld\n", query(, , n, a, b) + s[b] - s[a - ]);
else scanf("%d", &c), add(, , n, a, b, c);
}
return ;
}
L.vector会TLE改邻接表能过...***
dfs序 + 树状数组
#include <cstdio> const int maxn = ; int n, m, q, a[maxn], c[maxn], st[maxn], en[maxn]; int tot, head[maxn], to[maxn], next[maxn]; void ade(int x, int y) {
to[++ tot] = y, next[tot] = head[x], head[x] = tot;
} int lowbit(int x) {
return (x & (-x));
} int ask(int i) {
int res = ;
while(i > ) res += c[i], i -= lowbit(i);
return res;
} void add(int i, int x) {
while(i <= n) c[i] += x, i += lowbit(i);
} void dfs(int x, int f) {
a[x] = , st[x] = ++ m;
for(int y, i = head[x];i;i = next[i]) {
y = to[i];
if(y == f) continue;
dfs(y, x);
}
en[x] = m;
} char str[]; int x; int main() {
scanf("%d", &n);
for(int u, v, i = ;i < n;i ++) {
scanf("%d %d", &u, &v);
ade(u, v), ade(v, u);
}
dfs(, );
scanf("%d", &q);
while(q --) {
scanf("%s %d", str, &x);
if(str[] == 'Q') printf("%d\n", ask(en[x]) - ask(st[x] - ) + en[x] - st[x] + );
else {
if(a[x]) add(st[x], -), a[x] = ;
else add(st[x], ), a[x] = ;
}
}
return ;
}
bupt summer training for 16 #5 ——数据结构的更多相关文章
- bupt summer training for 16 #8 ——字符串处理
https://vjudge.net/contest/175596#overview A.设第i次出现的位置左右端点分别为Li,Ri 初始化L0 = 0,则有ans = sum{ (L[i] - L[ ...
- bupt summer training for 16 #7 ——搜索与DP
https://vjudge.net/contest/174962#overview A.我们发现重点在于x,y只要累加就ok了 在每个x上只有上下两种状态,所以可以记忆化搜索 f[0/1][i]表示 ...
- bupt summer training for 16 #6 ——图论
https://vjudge.net/contest/174020 A.100条双向边,每个点最少连2个边 所以最多100个点,点的标号需要离散化 然后要求恰好经过n条路径 快速幂,乘法过程就是flo ...
- bupt summer training for 16 #4 ——数论
https://vjudge.net/contest/173277#overview A.平方差公式后变为 n = (x + y)(x - y) 令 t = x - y ,变成 n = (t + 2x ...
- bupt summer training for 16 #3 ——构造
https://vjudge.net/contest/172464 后来补题发现这场做的可真他妈傻逼 A.签到傻逼题,自己分情况 #include <cstdio> #include &l ...
- bupt summer training for 16 #2 ——计算几何
https://vjudge.net/contest/171368#overview A.一个签到题,用叉积来判断一个点在一条线的哪个方向 可以二分,数据范围允许暴力 #include <cst ...
- bupt summer training for 16 #1 ——简单题目
D.What a Mess 给n个数,求其中能满足 a[i] % a[j] == 0 的数对之和 n = 1W,max_ai = 100W 不是很大,所以就直接筛就可以了 计算可得最高复杂度 < ...
- 数据结构和算法(Golang实现)(16)常见数据结构-字典
字典 我们翻阅书籍时,很多时候都要查找目录,然后定位到我们要的页数,比如我们查找某个英文单词时,会从英语字典里查看单词表目录,然后定位到词的那一页. 计算机中,也有这种需求. 一.字典 字典是存储键值 ...
- 【Android Developers Training】 16. 暂停和恢复一个Activity
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
随机推荐
- [luogu_U15118]萨塔尼亚的期末考试
https://zybuluo.com/ysner/note/1239615 题面 \(T\)次询问,求出\[\sum_{i=1}^n\frac{i}{\frac{n(n+1)}{2}}fib_i\] ...
- AcWing算法基础1.1
排序 快速排序(快排) 写题的时候用的不多基本都是直接sort ( ),面试可能要手撸快排,上模板 void quick_sort(int q[], int l, int r) { if(l > ...
- Linux 下文本查找技巧你掌握了吗?
前言 之前介绍过很多linux下查找相关的命令,例如<Linux中的文件查找技巧>,<find命令高级用法>,<如何查看linux中文件打开情况-lsof命令>等等 ...
- centos安装 memcached
.安装 yum -y update yum install -y libevent libevent-devel yum install -y memcached 2.配置 vi /etc/sysco ...
- HDU3949 XOR(线性基第k小)
Problem Description XOR is a kind of bit operator, we define that as follow: for two binary base num ...
- C# winform启动外部exe后,如何完全阻断父界面接收事件,扩展waitforexit
公司的系统搭载了好多奇奇怪怪的exe,以前启动exe后,系统还能接着操作.但是后面又提出额外的需求,说是打开外部exe之后,启动exe的父界面要完全不能进行任何操作.当然按常人所想再加一句waitfo ...
- JS高级——歌曲管理
1.将歌曲管理的CURD方法放到原型中 2.在构造函数中,我们只有一个属性是songList,因为音乐库不是共有的,如果将songList放入原型中,任何一个人的一次修改songList,都将把son ...
- CSS学习笔记----选择器
用过css的同志们都知道,选择器是非常重要的,如果选择器使用不当,即使你的css写的再好,但是不知道要用在哪个元素上,这不是英雄无用武之地吗? css,用过的都说好! 最基本的选择器,id选择器,类选 ...
- Cesium学习笔记(九):导入3D模型(obj转gltf)
在用cesium的过程中难免需要导入别人做好的3D模型,这时候就需要将这些模型转成gltf格式了 当然,官方也给了我们一个网页版的转换器,但是毕竟是网页版的,效率极其低下,文件还不能太大,所以我们就需 ...
- __declspec(dllexport)
__declspec(dllexport) (2010-06-17 10:04:28) 转载▼ 标签: __declspec dllexport 导出 it 分类: C 先看代码:以下是在dev-c+ ...