NOIP前夕模板整理第二弹:数据结构
来源:互联网 发布:淘宝网电动车阳伞 编辑:程序博客网 时间:2024/05/23 01:15
1、并查集
例题:家族
然而其实并查集的用处还有很多
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;int fa[100000];int find(int x){ return fa[x] == x?x:fa[x] = find(fa[x]);}int main(){ int n,m,p; scanf("%d%d%d",&n,&m,&p); for(int i =1; i <= n; i ++) fa[i] = i; for(int i = 1; i <= m; i ++) { int a,b; scanf("%d%d",&a,&b); if(find(a) != find(b)) { fa[find(b)] = find(a); } } for(int i = 1; i <= p; i ++) { int a,b; scanf("%d%d",&a,&b); if(find(a) != find(b)) puts("No"); else puts("Yes"); }}
2、线段树
例题:线段树练习3
支持区间修改,区间求和
(线段树练习1,2比较简单就不放了)
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#define MAXN 200000+5using namespace std;typedef long long ll;ll num[MAXN];struct tree{ ll sum,add,l,r;}tree[MAXN<<2];void build(ll l, ll r,ll p){ tree[p].l = l; tree[p].r = r; if(l == r) { tree[p].sum = num[l]; return ; } ll mid = (l+r)>>1; build(l,mid,p*2); build(mid+1,r,p*2+1); tree[p].sum = tree[p*2].sum + tree[p*2+1].sum; return ;}void spread(ll p){ if(tree[p].add) { tree[p*2].sum += (tree[p*2].r - tree[p*2].l + 1)*tree[p].add; tree[p*2+1].sum += (tree[p*2+1].r - tree[p*2+1].l + 1)*tree[p].add; tree[p*2].add += tree[p].add; tree[p*2+1].add += tree[p].add; tree[p].add = 0; return ; }}void change(ll l,ll r,ll p, ll x){ if(l <= tree[p].l && tree[p].r <= r) { tree[p].sum += (tree[p].r - tree[p].l + 1)*x; tree[p].add += x; return ; } spread(p); ll mid = (tree[p].l+tree[p].r)/2; if(l <= mid) change(l,r,p*2,x); if(r > mid) change(l,r,p*2+1,x); tree[p].sum = tree[p*2].sum + tree[p*2+1].sum; return ;}ll ask(ll l,ll r,ll p){ if(l <= tree[p].l&& tree[p].r <= r) { return tree[p].sum; } spread(p); ll mid = (tree[p].l + tree[p].r )/2; ll ans = 0; if(l <= mid) ans += ask(l,r,p*2); if(r > mid) ans += ask(l,r,p*2+1); return ans;}int main(){ ll n,q; ll a,b,c,x,y,z; scanf("%lld",&n); for(int i = 1; i <= n; i ++) { scanf("%lld",&num[i]); } build(1,n,1); scanf("%lld",&q); int t; for(int i = 1; i <= q; i ++) { scanf("%d",&t); if(t == 1) { scanf("%lld%lld%lld",&a,&b,&x); change(a,b,1,x); } if(t == 2) { scanf("%lld%lld",&y,&z); printf("%lld\n",ask(y,z,1)); } } return 0;}
(线段树的代码真的很长,所以来看树状数组)
3、树状数组
关于树状数组的思想,推荐一篇比较好的博客,其实我已经转载过来了,直接看我博客里的就行,233,链接:http://blog.csdn.net/cherish_k/article/details/53066617
(1)支持单点修改,区间查询(codevs1080 线段树练习)
单点修改:
#define lowbit(x) x&(~x+1)using namespace std;int a[MAXN],tree[MAXN],n,q;void add(int k,int x){ while(k <= n) { tree[k] += x; k += lowbit(k); }}
区间查询:
int read(int k){ int sum = 0; while(k) { sum += tree[k]; k -= lowbit(k); } return sum;}/*printf("%d\n",read(b) - read(a-1));//输出*/
(2)支持区间修改,单点查询(codevs1081 线段树练习 2)
修改和查询函数与上面是一样的,不过预处理的时候有所不同,这里只放主函数代码
int main(){ scanf("%d",&n); for(int i = 1; i <= n; i ++) { scanf("%d",&a[i]); add(i,a[i]); add(i+1,-a[i]); } scanf("%d",&q); int t; for(int i = 1; i <= q; i ++) { scanf("%d",&t); if(t == 1) { int a,b,x; scanf("%d%d%d",&a,&b,&x); add(a,x); add(b+1,-x); } if(t == 2) { int a; scanf("%d",&a); printf("%d\n",read(a)); } } return 0;}
(3)支持区间修改,区间查询(codevs1082 线段树练习 3)
对于上面两个例题,其实暴力就能过的,这个就不行了,还是老实打树状数组吧,虽然线段树也是能支持这三个操作的,但是树状数组短啊
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>#define MAXN 200000+5#define lowbit(x) x&(~x+1)using namespace std;typedef long long ll;ll a[MAXN],d1[MAXN],d2[MAXN],n,q;void add(ll *d,ll k,ll x){ while(k <= n) { d[k] += x; k += lowbit(k); }}ll read(ll *d,ll k){ ll sum = 0; while(k) { sum += d[k]; k -= lowbit(k); } return sum;}int main(){ scanf("%lld",&n); for(int i = 1; i <= n; i ++) { scanf("%lld",&a[i]); add(d1,i,a[i]); add(d1,i+1,-a[i]); add(d2,i,i*a[i]); add(d2,i+1,-a[i]*(i+1)); } scanf("%lld",&q); int t; for(int i = 1; i <= q; i ++) { scanf("%d",&t); if(t == 1) { int a,b,x; scanf("%d%d%d",&a,&b,&x); add(d1,a,x); add(d1,b+1,-x); add(d2,a,x*a); add(d2,b+1,-x*(b+1)); } if(t == 2) { int a,b; scanf("%d%d",&a,&b); printf("%lld\n",((b+1)*read(d1,b)-read(d2,b))-(a*read(d1,a-1)-read(d2,a-1))); } } return 0;}
最后放一个手写堆排吧,虽然还是sort快
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;int heap[200000],cnt;void push(int x){ cnt ++; int now = cnt; heap[now] = x; while(now != 1) { int fa = now /2; if(heap[now] < heap[fa]) { swap(heap[now],heap[fa]); now = now/2; } else break; } return ;}void pop(){ heap[1] = heap[cnt]; int now = 1; while(now*2+1 <= cnt) { int l = now*2,r = now*2+1; if(heap[l] < heap[now]) { if(heap[r] < heap[now] && heap[r] < heap[l]) swap(l,r); swap(heap[l],heap[now]); now = l; } else if(heap[r] < heap[now]) { swap(heap[r],heap[now]); now = r; } else break; } cnt --;}int main(){ int n,x; scanf("%d",&n); for(int i = 1; i <= n; i ++) { scanf("%d",&x); push(x); } for(int i = 1; i <= n; i ++) { printf("%d ",heap[1]); pop(); } return 0;}
1 0
- NOIP前夕模板整理第二弹:数据结构
- NOIP 前夕 模板整理
- NOIP前夕模板整理第一弹:图论
- NOIP 考前模板整理
- noip模板整理
- NOIP模板整理
- NOIP 模板整理
- 字符串数据结构模板整理
- 模板整理: 部分数据结构
- NOIP知识汇总及模板整理
- NOIP复赛知识点复习:算法/数据结构模板
- qwq不断更新的总结【NOIP前夕】
- 16年NOIP复赛前各种模板的整理
- NOIP 模板整理计划 NOIP2017 RP++(持续更新中~)
- NOIP模板
- 【数据结构第二周】线性表知识点整理
- 【数据结构第二周】堆栈知识点整理
- 【数据结构第二周】队列知识点整理
- POI终极解决方案:模板开发
- 直接选择排序算法
- Spark性能优化总结
- 软件工程——概述
- jQuery Validate验证框架详解
- NOIP前夕模板整理第二弹:数据结构
- 代码雨实现原理与代码分析
- 第11周项目1-验证算法(4)哈夫曼编码的算法验证
- 课堂知识总结
- 01_简单的环境配置php+基本知识点
- 关于c语言自加自减的分析
- 数据操纵语言
- 浅谈simhash及其python实现
- Linux下C开发工具介绍