heheda练数据结构

原创 2015年11月20日 22:20:37

联赛结束,自己的码力已经下降了不知多少个档次,再加上最近空闲时间比较多,我就开启了这个可以说最费时间的专题。

//话说我未完成的数论专题还会继续的。

最近看了以下知识点:

线段树套线段树

线段树套平衡树

准备学习:

替罪羊树

块状链表

复习:

树链剖分

树状数组套线段树

一些高级的线段树

可持久化tire

可并堆


bzoj 2957 楼房重建

给定第一象限的n个楼房,询问从原点能看到多少个楼房,支持修改楼房高度。

线段树维护每个点的斜率。

每个节点记录这个区间中最大的斜率,选取的个数。

修改一个点的斜率,它左面的答案是没有影响的。

对于右面,如果一个区间最大的斜率小于上一个的斜率,那么它的贡献为0.

否则,如果左区间最大值大于上一个的斜率,那么右区间答案不变,递归修改左子树。

如果小于,左区间贡献为0,递归修改右子树。

总时间复杂度nlog^2n 但是实际远远达不到。

注意:

1、右区间对当前区间的贡献不等于右区间的答案。

2、在某种情况下,double 类型的两个数是可能相等的。


bzoj 2741 L

询问区间中异或和最大的子段。 n,m 10^4 无修改,强制在线

分析:

区间是第一维数据结构,异或和最大是可持久化tire做一维数据结构。

于是,用分块维护区间答案,利用可持久化tire维护头尾答案。

预处理出每两块做左右边界的答案,暴力查询以最左面块的每个点开始的答案和以最右面块的每个点结束的答案。


bzoj 3130 k大数查询

有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

注意这不是带插入区间k大值。

学cdq的时候用一种神奇的树状数组水过。线段树套线段树的第一维不支持标记,但是第二维支持。第一维权值,第二维位置,生写即可。

第一次写下放标记的动态开点线段树,大约就是release的时候把左右儿子都建出来。

话说学cdq的时候把题刷了个遍,现在几乎找不到树套树没写过的题了。


bzoj 3196 二逼平衡树

线段树套平衡树的各项操作。每个线段树的节点是这个区间的平衡树。

第一维区间,第二维权值。

注意一开始把树建出来,而不是一个个插入。要不就卡常数了。

注意两个点权值相等的情况


bzoj 2333 棘手的操作

挖坑。

话说堆就是维护最大值的,我还维护一个变量干什么?

调了n天的代码,还是贴一下吧。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define ll long long
#define inf 1e9
#define eps 1e-10
#define md
#define N 300010
using namespace std;
int ad[N],ch[N][2],val[N],dis[N],fa[N],q[N],father[N];
multiset<int> st;
int All;
int findfa(int x) { return father[x]==x?x:father[x]=findfa(father[x]);} 
void release(int x)
{
	if (ad[x])
	{
		int l=ch[x][0],r=ch[x][1],d=ad[x];
		if (l)
		{
			ad[l]+=d; val[l]+=d;
		}
		if (r)
		{
			ad[r]+=d; val[r]+=d;
		}
		ad[x]=0;
	}
}

void update(int x)
{
	//mx[x]=val[x];
	//if (ch[x][0]) mx[x]=max(mx[x],mx[ch[x][0]]);
	//if (ch[x][1]) mx[x]=max(mx[x],mx[ch[x][1]]);
	if (dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
	dis[x]=dis[ch[x][1]]+1;
}

int merge(int x,int y)
{
	//printf("merge %d %d\n",x,y);
	if (!x) return y;
	if (!y) return x;
	if (val[x]<val[y]) swap(x,y);
	release(x);
	ch[x][1]=merge(ch[x][1],y);
	fa[ch[x][1]]=x;
	update(x);
	return x;
}

void push_down(int x)
{
	int w=0;
	while (x)
	{
		 q[++w]=x; x=fa[x];
	}
	for (int i=w;i;i--) release(q[i]);
}

void push_up(int x)
{
	while (x)
	{
		update(x);
		x=fa[x];
	}
}

int find(int x)
{
	while (fa[x]) x=fa[x];
	return x;
}

int split(int x)
{
	int f=merge(ch[x][0],ch[x][1]);
	if (fa[x]) ch[fa[x]][ ch[fa[x]][1]==x ]=f;
	fa[f]=fa[x];
	fa[x]=ch[x][0]=ch[x][1]=0;
	update(x); push_up(f);
	return find(f);
}

void addit(int x,int d)
{
	int root=find(x);
	push_down(x);
	st.erase(st.find(val[root]));
	val[x]+=d;
	root=split(x);
	root=merge(root,x); fa[root]=0;
	st.insert(val[root]);
}

void addheap(int x,int d)
{
	int root=find(x);
	st.erase(st.find(val[root]));
	ad[root]+=d; val[root]+=d; //mx[root]+=d;
	st.insert(val[root]);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("data.in","r",stdin); freopen("data.out","w",stdout);
#endif
	int n;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&val[i]);
		//mx[i]=val[i];
		st.insert(val[i]);
	}
	for (int i=1;i<=n;i++) father[i]=i;
	char str[5];
	int m;
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%s",str);
		//printf("st %s\n",str);
		if (str[0]=='U')
		{
			int x,y;
			scanf("%d%d",&x,&y);
			push_down(x); push_down(y);
			int f1=findfa(x),f2=findfa(y);
			if (f1==f2) continue;
			father[f1]=f2;
			f1=find(x); f2=find(y);
			st.erase(st.find(val[f1])); st.erase(st.find(val[f2]));
			f1=merge(f1,f2); fa[f1]=0;
			st.insert(val[f1]);
		}
		else if (str[0]=='A')
		{
			int x,d;
			if (str[1]=='1')
			{
				scanf("%d%d",&x,&d);
				addit(x,d);
			}
			else if (str[1]=='2')
			{
				scanf("%d%d",&x,&d);
				addheap(x,d);
			}
			else //if (str[1]=='3')
			{
				scanf("%d",&d);
				All+=d;
				//printf("all %d %d\n",d,All);
			}
			//else printf("? %s\n",str);
		}
		else
		{
			int x;
			if (str[1]=='1')
			{
				scanf("%d",&x);
				push_down(x);
				printf("%d\n",val[x]+All);
			}
			else if (str[1]=='2')
			{
				scanf("%d",&x);
				printf("%d\n",val[find(x)]+All);
			}
			else
			{
				int a=*--st.end(); //printf("a %d\n",a);
				printf("%d\n",a+All);
			}
		}
	}
}


bzoj 4009 接水果

挖坑。


bzoj 4336 骑士的旅行

挖坑,已经尝试了权值线段树套平衡树和线段数套线段树,都过不了,改天有心情写一个常数20的线段树,或许能过?


11.28更

这个周主要做了各个数据结构的一些裸题。

bzoj 1146 骑士的旅行 线段树套平衡树+树链剖分+线段树上二分。

bzoj 2733 永无乡

开始想要 splay+启发式合并,感觉有点虚,就看了hzwer的线段树合并,感觉好扯,但是,细想想,复杂度是有保证的。

需要merge的线段树节点一定是两颗线段树共有的,那么一定少于小的线段树的节点数,所以小线段树的size就扩大了2倍,最多扩大log次,也就是启发式合并的复杂度分析。


bzoj 4012 开店

这是我这个周唯一写的不是太裸的题了吧。



蒟蒻的noip2015滚粗记

oi就是一场实力与运气的博弈——题记        也不知道这会不会是自己的最后一年noip,也不知道2016夏绵阳见是什么样子。但是,第三年的noip,还是值得回味的。 Day 0      ...
  • heheda_is_an_OIer
  • heheda_is_an_OIer
  • 2015年11月16日 18:48
  • 1620

数据结构总结

分类 1:并查集 2:单调队列、单调栈 3:堆、优先队列 4:树状数组 5:线段树 6:树链剖分 7:主席树 8:平衡树 9:lct 10:树套树 11:分块、莫队...
  • running_in_dark
  • running_in_dark
  • 2016年09月25日 16:53
  • 350

heheda练数据结构

联赛结束,自己的码力已经下降了不知多少个档次,再加上最近空闲时间比较多,我就开启了这个可以说最费时间的专题。 //话说我未完成的数论专题还会继续的。 最近看了以下知识点: 线段树套线段树 线段树套平衡...
  • heheda_is_an_OIer
  • heheda_is_an_OIer
  • 2015年11月20日 22:20
  • 1766

heheda~

今天没有可描述的心情,。但是我想对自己说,要坚持! Private Sub Command1_Click()   Me.Font.Size = 70   'Print Hex(230)  ...
  • rhshuang
  • rhshuang
  • 2016年05月07日 17:48
  • 64

数据结构——滑动窗口练习

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,...
  • suanzhaogao
  • suanzhaogao
  • 2017年05月23日 15:19
  • 250

Ajax实现增删改查的demo

  • 2017年04月01日 23:30
  • 1023KB
  • 下载

数据结构小练

孩子-兄弟法存储树并求结点数 #include #include int sum=0; typedef struct node{ int data; struct node *firstchild...
  • kavu1
  • kavu1
  • 2015年11月13日 19:21
  • 271

CH06_EX33&nbsp;数据结构Anyview练…

6.33③  假定用两个一维数组L[1..n]和R[1..n]作为 有n个结点的二叉树的存储结构, L[i]和R[i]分别指 示结点i的左孩子和右孩子,0表示空。试写一个算法 判别结点u是否为结点v的...
  • jingzhewangzi
  • jingzhewangzi
  • 2014年08月29日 22:27
  • 310
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:heheda练数据结构
举报原因:
原因补充:

(最多只允许输入30个字)