随笔分类 -  数据结构

摘要:已经做过一个类似的题目了,只是这道题目求的是最长的长度,那个题目求的是总的这样的序列的个数,都是用线段树或者树状数组来优化求和操作,使之降为log(n)View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 100010;int sum[maxn<<2];int num[maxn];int 阅读全文
posted @ 2012-04-08 19:47 Because Of You 阅读(388) 评论(0) 推荐(0)
摘要:题目链接http://www.codeforces.com/problemset/problem/145/E蛮好的题目一连串由4、7组成的字符串两种操作:count 输出整个区间内最长的不下降子序列的长度switch a b 将a、b之间的数4变成7 7变成4注意,最长不下贱子序列不一定要连续一般情况下,不连续的最长不下降子序列的长度是无法维护的,但是这道题目的特殊性显而易见,只有4 7 两种数字,相当于0 1做法:1:分别记录区间最长不下降和最长不上升的序列的长度,这样子进行异或操作的时候可以直接互换2:记录区间0的个数和1的个数,利用这两个信息可以 在将信息往上传的时候 维护区间最长的.. 阅读全文
posted @ 2012-04-03 18:45 Because Of You 阅读(452) 评论(0) 推荐(0)
摘要:可以用来锻炼线段树基本功这种题思路基本不用怎么想,固定好代码框架,往里面填代码就好了,但要绝对仔细因为有异或操作,所以要把白色和黑色的信息都记录下来,在更新的时候可以互换View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 111111;int sum[maxn<<2];int lb[m 阅读全文
posted @ 2012-04-03 10:07 Because Of You 阅读(1340) 评论(0) 推荐(0)
摘要:链接:http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=23701题意:求n个点的最大公约数,有两种操作,增加一个数,删去一个数,删去的数肯定是已经存在的离线处理,先要离散化然后找到每个数相应的位置插入或删除,简单的单点更新gcd(a,b,c,d)=gcd(gcd(a,b),gcd(c,d));View Code #include<cstdio>#include<vector>#include<cstring>#include<algorithm>using names 阅读全文
posted @ 2012-03-28 21:29 Because Of You 阅读(794) 评论(0) 推荐(0)
摘要:2A的题,因为注释没去完。。。。。。题意:给你n个数,求长度大于2的且相邻数字绝对值差不超过H的序列的个数很容易想到一个朴素的O(n^2)DPdp[i]=sigma(dp[j],abs(val[i]-val[j])<=H)由于DP转移过程是求和的操作,所以可以用树状数组来优化求和操作进一步转换:val[i]-H<=val[j]<=val[i]+H,所以每次把val[i]-H到val[i]+H之间的树状数组中的数求和 假设和为pre,dp[i]=pre+1;表示以i结尾的序列的个数序列长度>=1,求和后再把dp[i]放进树状数组即可最后的答案还要减掉n,取出长度为1的序列 阅读全文
posted @ 2012-03-28 11:21 Because Of You 阅读(611) 评论(0) 推荐(0)
摘要:http://codeforces.com/problemset/problem/160/E题意 :一条直线上有很多车站有n辆车 每辆车的信息是 s,f,t 出发的站点,目的地,以及出发的时间,中途可以在其他站停留m个乘客 每个乘客的信息是 start ,to ,tx 出发的站点 要到的站点 出发时间如果一个乘客能够做上某辆车必须满足s<=start,to<=f,tx<=t而且要满足车的出发时间越早越好。输出时每个乘客应该坐上的车,如果没有输出-1限制条件比较多,出发点 终点 时间都要题目满足要求,而且要在满足前两者的情况下,出发的尽可能早首先很容易想到排序,把汽车和乘客的信 阅读全文
posted @ 2012-03-28 10:05 Because Of You 阅读(395) 评论(0) 推荐(1)
摘要:View Code #include<cstdio>#include<cstring>int hash[2000010];int main(){ int a,b,c,d,i,j; while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF) { if( (a>0 && b>0 && c>0 && d>0 )|| (a<0 && b<0 && c<0 && d&l 阅读全文
posted @ 2012-03-25 04:15 Because Of You 阅读(328) 评论(0) 推荐(0)
摘要:第一次设计哈希函数,乱YY的,哈希函数细微的不同时间差距很大啊,我交了n遍。。。disscuss中的哈慈函数好强大。。x,y映射到一个哈希值,有可能会有多个值具有同一哈希值,所以建立邻接表,哈希函数的目的就是让尽量少的数拥有同一个哈希值也就是尽可能的分散,尽可能的做到一一映射,就做了这题我就感觉哈希好强大啊这是我看别人的代码后的理解,不知道对不对感觉是对的,因为能A题,呵呵。题目中已知两个点(相邻),可以求出正方形的另外两个点http://iaml.is-programmer.com/posts/7923.html已知两个点,可以得出得出另外两个点 (x1+|y1-y2|, y1+|x1-x2 阅读全文
posted @ 2012-03-25 03:42 Because Of You 阅读(424) 评论(0) 推荐(0)
摘要:题意:一幅图,至多有一个点的度数大于2,,然后有三种操作,给每条边染成黑色或白色,询问两个点间的黑色路径的距离是多少(即两个点有黑色路径相连而成)。找出那个度数大于2的点,没有的话就是一条链。有几个度就有几条链,对于每个操作,找到每个点相应的链,和这个点是这条链上的第几个点,用树状数组做就可以了。考察图的模拟,二维树状数组或线段树学习了别人的代码View Code #include<cstdio>#include<cstring>#include<vector>#include<cstdlib>#include<algorithm>u 阅读全文
posted @ 2012-03-21 13:24 Because Of You 阅读(398) 评论(0) 推荐(0)
摘要:当线段树调试不出来的时候,请画一棵树,设个断点,照着你的树走,走完你就AC了和poj 2528的离散化方法如出一辙,如果两个相邻数的大小大于1 ,在中间插入一个任意的数线段树更新的过程类似于求周长并,需要判断左右边界是否是一样的高度(左儿子的右边界与右儿子的左边界)我是左闭右闭的线段树,所以开始的时候要把n-1加进来(这里错了好几次,一直加了n) ,另外0也要加进来。举个例子:区间长度为10 现在总共记录了1 3 5 7所以要先把0 9 加进来离散化后是0 1 2 3 4 5 6 7 8 9下面这个函数其实是把两个功能结合在一起了View Code void pushup(int rt,int 阅读全文
posted @ 2012-03-19 21:51 Because Of You 阅读(663) 评论(1) 推荐(1)
摘要:转自:http://www.notonlysuccess.com/index.php/segment-tree-complete/题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报思路:这题数据范围很大,直接搞超时+超内存,需要离散化:离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了所以离散化要保存所有需 阅读全文
posted @ 2012-03-19 12:16 Because Of You 阅读(5511) 评论(0) 推荐(1)
摘要:单点更新就好了,简单题一开始以为可以不连续,想来想去都觉得哪里不对劲,感觉无法解决,囧。。。。#define max(a,b) ((a)>(b)?(a):(b)) 要注意加括号,因为没注意这个细节错了蛮久线段树的三个域lm[rt]:从左开始最长的连续递增子序列rm[rt]:以右边界结尾的最长的。。。。mx[rt]:管辖区间内最长的。。。。。如果num[mid]<num[mid+1],可以对区间上的域进行合并还没那个hotel难View Code #include<cstdio>#include<cstring>#include<algorithm> 阅读全文
posted @ 2012-03-17 22:44 Because Of You 阅读(238) 评论(0) 推荐(0)
摘要:http://acm.hrbeu.edu.cn/index.php?act=problem&id=1001&cid=19View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100010;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int ok[maxn<<2];void build(int l,int r,int 阅读全文
posted @ 2012-03-15 21:32 Because Of You 阅读(389) 评论(0) 推荐(0)
摘要:有点特殊,每个长方体的底面的左下角都在(0,0 , 0)所以计算面积的时候就简单很多了。用线段树,对x坐标建树rm[rt]:区间最右端y值mx[rt]:管辖区间内最大的y值sum[rt]:管辖区间内的总面积cover[rt]:是否被某个y值完全覆盖求体积的时候,从下往上不好求因为如果y大的长方体在下面,y小的在上面,从下往上计算的时候会多算比如 5 5 5 1 1 10两个长方体,在计算5到10的体积时,面积并的和是25,实际上是1而从上往下求体积就不会出现这种问题View Code #include<cstdio>#include<cstring>#include&l 阅读全文
posted @ 2012-03-14 11:35 Because Of You 阅读(516) 评论(0) 推荐(0)
摘要:http://www.cppblog.com/menjitianya/archive/2011/04/06/143506.html关键是如何求最少的交换次数,用到了简单哈希#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long lld;#define lowbit(x) (x&-x)const int maxn = 100010;int c[maxn],hash[maxn],val[maxn],a[maxn];void upda 阅读全文
posted @ 2012-03-08 22:03 Because Of You 阅读(332) 评论(1) 推荐(0)
摘要:hdu 3577 也是这样的题目典型的线段树区间覆盖,懒惰标记要多记录两个域,一个是区间内最大值所在的最左的位置,另一个是最右的位置View Code //zoj 3573#include<stdio.h>#include<cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mid (l+r)>>1const int maxn = 100010;int sum[maxn<<2];//子树区间内最大的覆盖次数int col[maxn<<2 阅读全文
posted @ 2012-03-01 14:10 Because Of You 阅读(414) 评论(0) 推荐(0)
摘要:先把中缀表达式转换成表达式树保存下来,再用后缀表达式计算,过程比较繁琐所幸最后还是封装成了一个类写的很挫的View Code #include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<iostream>using namespace std;int flag;bool pre;class calc{ enum Type { DATA,ADD,SUB,MULTI,DIV,OPAREN,CPAREN,EOL}; struct node { T 阅读全文
posted @ 2012-02-25 11:18 Because Of You 阅读(310) 评论(0) 推荐(0)
摘要:做了两个多小时。。。。其实也还好求至少有三个长方体重叠的区域的体积交对z轴坐标离散化,对于每个高度,记录包含该高度的长方体的下表面,求至少覆盖三次的面积并求面积交同那道“覆盖的面积”,只不过这里是覆盖三次,稍微想的仔细一点应该不成问题再乘以(z[i+1]-z[i]),易知z[i+1]==所记录的长方体上表面的高的最小值,所以不用担心这样做的正确性View Code #include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 lld;const 阅读全文
posted @ 2012-02-16 23:21 Because Of You 阅读(1005) 评论(3) 推荐(0)
摘要:同上一题一样,记录dfs遍历的序列,然后再利用树状数组快速求和调了好久呢View Code #include<cstdio>#include<stack>#include<cstring>using namespace std;stack<int> ss;const int maxn = 100010;struct EDGE{ int v,next;}edge[maxn*2];int exis[maxn],head[maxn],l[maxn],r[maxn],seq[maxn*2],re[maxn],c[maxn*2],cnt;bool vis[ 阅读全文
posted @ 2012-02-14 14:20 Because Of You 阅读(230) 评论(0) 推荐(0)
摘要:一棵树,求每个结点的子树中有几个数是小于这个数的dfs会进入一个点一次,出一个点一次,中间经过的点都是它的子树中的点,所以,进入的时候统计一遍,出来的时候统计一遍,两个结果相减就可以了纯dfs会爆栈,要模拟栈。不过,不模拟栈也可以过,在网上看到c++可以设置栈的大小,所以把栈空间设置的大一点直接dfs做就可以了View Code #pragma comment(linker,"/STACK:100000000,100000000")#include<cstdio>#include<cstring>const int maxn = 100010;str 阅读全文
posted @ 2012-02-13 20:47 Because Of You 阅读(747) 评论(2) 推荐(0)