/*Day1、Day2我尽量整理吧*/

树状数组

树状数组滋瓷单点修改和前缀查询

加特技可以使得树状数组支持更多操作。

c[2n+1]=a[2n+1](奇数就是它本身)

c[2n]≠a[2n](偶数不是)

二进制表示1~8

  1. dec bin
  2. 1 0001
  3. 2 0010
  4. 3 0011
  5. 4 0100
  6. 5 0101
  7. 5 0110
  8. 7 0111
  9. 8 1000

一个数包含的位数和它二进制最后一个1的位置有关。

c[x]=a[x-lowbit(x)+1]+...+a[x]

-x=2^32-x

lowbit(x)=x&(-x);

莫名其妙地翻到了以前写的博客:

求和:x每次减去lowbit(x)

代码:

  1. void add(int x,int y)//第x项+y
  2. {
  3. for(;x<=n;x+=x&-x)
  4. c[x]+=y;
  5. }
  6. int ask(int x)//第x项的前缀和
  7. int y=0;
  8. for(;x;x-=x&-x)
  9. y+=c[x];
  10. return y;
  11. }

复杂度均为:O(log2n)

NOIP2013 火柴排队

匹配方法:按照排序位置匹配

让a中第k大和b中比k大匹配

同时移动a,b与只移动一个没有区别,可以确定一个移动一个。

首先:离散化:Ai表示ai是a数组第几大的,Bi表示bi是b数组中第几大的

离散化之后,火柴的高度已经没有意义了,只要能够表示出是第几大就行

定义数组C满足C[A[i]]=i,D满足D[i]=C[B[I]],表示b数组的第i项最终需要移动到哪一位

然后求D数组中的逆序对数即可。前后枚举每一项,用树状数组维护D

  1. int main()
  2. {
  3. for(i=1;i<=n;i++)
  4. A[i]=a[i];
  5. sort(a+1,a+n+1);//给a数组从小到大排序
  6. for(i=1;i<=n;i++)
  7. A[i]=lower_bound(a+1,a+n+1,A[i])-a;
  8. //通过lower_bound搜到A[i](原来的a[i])在排序后的数组中的排名是第几小的
  9. for(i=1;i<=n;i++)
  10. B[i]=b[i];
  11. sort(b+1,b+n+1);
  12. for(i=1;i<=n;i++)
  13. B[i]=lower_bound(b+1,b+n+1,B[i])-b;
  14. //B[i]同A[i]
  15. //A[i]表示a[i]是a数组中第几小的 ——hzh
  16. //C[i]表示a数组第i小的数的下标 ——hzh
  17. for(i=1;i<=n;i++)C[A[i]]=i;//C[i]表示a数组第i小的数的下标
  18. for(i=1;i<=n;i++)D[i]=C[B[i]];//B[i]是b[i]的排名
  19. //C[B[i]]是b[i]对应的排名相等a[i]下标;即D[i]是b[i]对应的a[i]的位置
  20. //C[B[i]]表示a数组中第B[i]小的数的下标 ——hzh
  21. //D[i]表示b数组中第i个数应该移动到哪个位置 ——hzh
  22. }

然后用计数排序的思想求逆序对:

当D数组遍历到i的时候,我们要找的就是在D数组中i的右边且小于i的元素数量。此时所有在D数组i的右边元素的树状数组中已经标记了个"1"(默认0),而所有小于i的元素在树状数组中都在i的左边。所以,我们只需要求树状数组中i的前缀和,就是D数组中i的右边且小于i的元素的数量。然后把这个结果更新到ans中(ans+=ask(i))。遍历完i后,在树状数组中的i标记一个1(add(i,1)),然后遍历i-1。

野鸡题(实为http://poj.org/problem?id=3468)
区间价一个数,区间求和

差分:
区间加一个数,单点求值的树状数组(差分)
差分:一项减去前一项
代码:配套前面的树状数组代码用

  1. add(l,x);
  2. add(r+1,-x);//区间[l,r]增加x权值
  3. ask(x);//查询x点的权值

野鸡题:两个树状数组解决 贼难!!

  1. 0 0 0 0 0//初始值
  2. [2,4]+3
  3. 0 3 3 3 0 //修改后的值
  4. 0 3 6 9 9 //修改后的前缀和
  5. -3 0 0 12 0 //第一个树状数组
  6. -3 -3 -3 9 9 //第一个树状数组前缀和
  7. 3 0 0 -3 0 //第二个树状数组:对第一个树状数组的错误进行修正
  8. 3 3 3 0 0 //第二个树状数组前缀和
  9. 3 6 9 0 0 //第二个树状数组每一项前缀和乘以下标
  10. 0 3 6 9 9 //乘以下标之后加上第一个树状数组的前缀和
  11.  
  12. add(l,r,x)
  13. {
  14. add1(l-1,-x*(l-1));
  15. add1(r,x*r);
  16. add2(l-1,x);
  17. add2(r,-x);
  18. }
  19. ask(l,r)=ask1(r)+ask2(r)*r-(ask1(l-1)+ask2(l-1)*(l-1))

bzoj1878 SDOI2009 HH的项链

用离线的方法做,把所有询问按照一定的顺序做,按照r从小到大排序

1 2 5 2 3 3 5

以代码为生的我
    for(i=1;i<=n;i++)
    {
        f[i]=g[a[i]];
        g[a[i]]=i;//处理f数组
        add(f[i]+1,1);
        add(i+1,-1);//区间[f[i]+1,i]增加1
        for(;q[j].r==i&&j<=n;j++)
            q[j].ans=ask(q[j].l);//处理询问
    }

O(nlog2n)

二叉搜索树——BST(也叫作平衡树)

左儿子<根节点<右儿子,左子树和右子树也是二叉搜索树

treap.每个节点有一个随机的额外权值,这个随机权值满足堆的性质

treap的旋转 右旋、左旋

旋转不改变平衡的性质,堆的随机权值是为了保持平衡

代码

  1. void rotate(int x)
  2. {
  3. int y=dad[x],z=dad[y];
  4. bool f=s[1][y]==x;
  5. if(!is_root(y))s[s[1][z]==y][z]=x;
  6. s[f][y]=s[!f][x];s[!f][x]=y;
  7. dad[x]=z;dad[y]=x;dad[s[f][y]]=y;
  8. update(x);update(y);
  9. }

Afternoon!

treap 有两个权值,一个平衡树的权值;一个堆的权值;性质(略)

在保证两个权值唯一相等,这个数是唯一确定的(!?!??!!??!?!)

旋转操作:P是Q左儿子->右旋->Q是P右儿子

Q是P右儿子->P是Q的左儿子

旋转之后,中序遍历是一样的,且满足平衡树的性质

如何满足堆的性质?

加入一个点 ——(x,?)

从root开始“二分查找”,钦点(x,?)的位置

为了满足堆的性质,判断是怎样交换节点,要左旋还是右旋

然后转来转去把它转成treap

treap代码

  1. void left_rotate(int &q,int p)//
  2. {
  3. rs[q]=ls[p];
  4. ls[p]=q;
  5. q=p;
  6. }
  7. void right_rotate(int &q,int p)//
  8. {
  9. ls[q]=rs[p];
  10. rs[p]=q;
  11. q=p;
  12. }
  13. void add(int x,int &cur)
  14. {
  15. if(!cur)
  16. {
  17. cur=++cnt;
  18. V[cnt]=x;
  19. R[cnt]=rand();
  20. return;
  21. }
  22. if(x>V[cur])
  23. {
  24. add(x,rs[cur]);
  25. if(R[rs[cur]]<R[cur])
  26. left_rotate(cur,rs[cur]);
  27. }
  28. else
  29. {
  30. add(x,ls[cur]);
  31. if(R[ls[cur]]<R[cur])
  32. right_rotate(cur,ls[cur]);
  33. }
  34. }
  35. void del(int x,int &cur)
  36. {
  37. if(V[cur]==x)
  38. {
  39. if(!ls[cur]||!rs[cur])
  40. {
  41. cur=ls[cur]|rs[cur];
  42. return;
  43. }
  44. if(R[ls[cur]]>R[rs[cur]])
  45. {
  46. left_rotate(cur,rs[cur]);
  47. del(x,ls[cur]);
  48. }
  49. else
  50. {
  51. right_rotate(cur,ls[cur]):
  52. del(x,rs[cur]);
  53. }
  54. }
  55. else
  56. if(x<V[cur])del(x,ls[cur]);
  57. else
  58. del(x,rs[cur]);
  59. }

Splay

Zig-Zig操作

Zig-Zag操作

添加节点:

和treap类似,在过程中不需要rotata,再查完之后需要将插入的元素进行一遍splay(整个做完add之后再splay,是并列的不是套着的)

删除元素:

如果这元素只有一儿子,让这儿子当做他

如果有两个儿子;从左子树找最大的或者右子树找最小的

代码:太难了

  1. void splay(int x)
  2. {
  3. st[t=1]=x;
  4. for(int y=x;!is_root(y);st[++t]=y=dad[y]);
  5. for(;t;t--)if(rev[st[t]])reverse(st[t]);
  6. for(;!is_root(x);rotate(x))if(!is_root(dad[x]))
  7. s[0][dad[x]]==x^s[0][dad[dad[x]]]==dad[x]?rotate(x):rotate(dad[x]);
  8. update(x);
  9. }
  10. int find_max(int cur)
  11. {
  12. for(;s[1][cur];cur=s[1][cur]);
  13. return cur;
  14. }
  15. void combine(int &cur,int cur1)
  16. {
  17. cur=find_max(cur);//找到一棵树最大的节点
  18. splay(cur);
  19. rs[cur]=cur1;
  20. }

fhq-treap(不讲)

替罪羊树

朝鲜树:不旋转 add找到在哪里插,然后直接插进去

玄学的替罪羊树:最快的平衡树.........媲美RBT(msRBT更快????)

Problem:bzoj3224/bzoj3223

STL

pair(对) pair<int,int>  make_pair(x,y) sort排序用

priority_queue(堆)

priority_queue<pair<int,int> >q;//两个>之间有个空格

map 映射(hash) 红黑树 定义:map<int,int>a; 赋值:a[x]=y; 取值:cout << a[x];

set 功能:insert upper_bound lower_bound size clear begin end 迭代器支持++ --

multiset 删除一个数会把所有这个数删掉

bitset<数>Bit; bit[数]=1; bit<<=100; (int)bit[xxx]; count() O(n) size没用 reset有用 flip 转位 bit=~Bit也可

线段树

直接放代码一波(+lazy tag的)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. void pushdown(int cur,int x)
  4. {
  5. cov[cur<<1]+=cov[cur];
  6. cov[cur<<1|1]+=cov[cur];
  7. sum[cur<<1]+=cov[cur]*(x+1>>1);
  8. sum[cur<<1|1]+=cov[cur]*(x>>1);
  9. cov[cur]=0;
  10. }
  11. void update(int cur)
  12. {
  13. sum[cur]=sum[cur<<1]+sumpcur<<1|1];
  14. }
  15. void add(int l,int r,int L,int R,int x,int cur)
  16. {
  17. if(L=<l&&R>=r)
  18. {
  19. cov[cur]+=x;
  20. sum[cur]+=(r-l+1)*x;
  21. return x;
  22. }
  23. if(cov[cur])
  24. pushdown(cur,r-l+1);
  25. int mid=l+r>>1;
  26. if(L<=mid)
  27. add(l,mid,L,R,x,cur<<1);
  28. if(R>mid)
  29. add(mid+1,r,L,R,x,cur<<1|1);
  30. update(cur);
  31. }
  32. int query(int l,int r,int L,int R,int cur)
  33. {
  34. if(L<=l&&R>=r)
  35. return sum[cur];
  36. if(cov[cur])
  37. pushdown(cur,r-l+1);
  38. int mid=l+r>>1,ans=0;
  39. if(L<=mid)
  40. ans+=query(l,mid,L,R,cur<<1|1);
  41. return ans;
  42. }

problems:

tyvj1473 校门外的树3

开两个线段树,一个存左边界另一个存右边界,m-2的时候求[1,l-1]之间的右边界数【求得是左边不再要查找区间内的线段数】ans1和[r+1,n]的左边界数【求的是右边不在要查找区间内的线段树】ans2,ans=tot_line-ans1-ans2

codevs1299:切水果

N个东西,每次标记[L,R]的东西,并求出没有被标记的数量

对于线段树上每个节点维护sum标记,表示这个节点对应区间中剩下水果数量。每次输出sum[1] 时间复杂度O(nlog2n)

bzoj4373

区间组成等差数列条件:

max[l,r]-min[l,r]=(r-l)*k.

差分gcd=k

修改:把他与前后两个数差分改了就行

最大值和最小值不能用ST表,请用线段树,因为他要修改

时间复杂度=O(nlog22n)

trie树(踹树???)

字典树、单词查找树

三个基本性质

根节点不包含字符,除了根节点外每一个节点都只包含一个字符。

从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串

每个节点的所有子节点所有包含的字符不相同

踹树是“26叉树”,只是一些没有儿子的节点我们会忽略(就是不需要的字符忽略掉)

代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main()
  4. {
  5. scanf("%d",&n);
  6. for(int i=1;i<=n;i++)
  7. {
  8. scanf("%s",s[i]+1);
  9. m=strlen(s[i]+1);
  10. for(j=1,cur=root;j<=m;j++)
  11. if(son[cur][s[j]-'a'])
  12. cur=son[cur][s[j]-'a'];
  13. else
  14. cur=son[cur][s[j]-'a']=++cnt;
  15. tot[cur]++;
  16. }
  17. }

于是他错误的点名开始了????这什么破题目名字

luogu2580

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int main(){
  4. scanf("%d",&n);
  5. root=1;
  6. for(i=1;i<=n;i++){
  7. scanf("%s",s+1);
  8. m=strlen(s+1);
  9. for(j=1,cur=root;j<=m;j++)
  10. if(son[cur][s[j]-'a'])cur=son[cur][s[j]-'a'];
  11. else cur=son[cur][s[j]-'a']=++cnt;
  12. tot[cur]=1;
  13. }
  14. scanf("%d",&m);
  15. for(i=1;i<=n;i++){
  16. scanf("%s",s+1);
  17. m=strlen(s+1);
  18. for(j=1,cur=root;j<=m;j++)
  19. cur=son[cur][s[j]-'a'];
  20. if(tot[cur]==1)puts("OK"),tot[cur]=-1;
  21. else if(tot[cur]==-1)puts("REPEAT");
  22. else puts("WRONG");
  23. }
  24. }

luogu2292 L语言

字典建踹树,然后一个一个字符匹配去吧。。。O(n*m)

Luogu2922 秘密消息

信息建踹树,一个节点的标记表示以这个节点为结尾的信息数量,然后每个密码从根节点遍历,遍历到头之后求经过路径的标记和,然后求以这个节点为子树的标记和

BZOJ3261 最大异或和

用前缀异或建踹树,

函数式线段树

president树

可持久化线段树(可反悔线段树)

主席树:

  1. void add(int l,int r,int x,int y,int &cur,int cur1)
  2. {
  3. cur=++cnt;
  4. sum[cur]=sum[cur1]+y;
  5. ls[cur]=ls[cur1];
  6. rs[cur]=rs[cur1];
  7. if(l==r)
  8. return;
  9. int mid=l+r>>1;
  10. if(x<=mid)
  11. add(l,mid,x,y,ls[cur],ls[cur1]);
  12. else
  13. add(mid+1,r,x,y,rs[cur],rs[cur1]);
  14. }
    int ask(int l,int r,int k,int cur,int cur1)
    {
        if(l==r)return l;
        int mid=l+r>>1;
        if(sum[ls[cur]]-sum[ls[cur1]]>=k)
            return ask(l,mid,k,ls[cur],ls[cur1]);
        else
            return ask(mid+1,r,k-sum[ls[cur]]+sum[ls[cur1]],rs[cur],rs[cur1]);
    }
    int main()
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            add(1,n,x,y,root[i],root[i-1]);
    ask(1,n,k,root[r],root[l-1]);
        }
    }

空间:nlog2n

来自:http://www.jianshu.com/p/e6050f01c4bc

字符串hash MD5

字符串转换成高进制大整数

hash:大数/巨数(或字符串)变比较小的

01串翻转问题(课件P450)

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int main(){
  4. scanf("%d",&n);
  5. for(i=0;i<n;i++)scanf("%d",&x),a[i]=x;
  6. scanf("%d",&t);
  7. for(i=1;i<=t;i++){
  8. scanf("%d",&l[i]);
  9. for(j=0;j<l[i];j++)scanf("%d",&x),b[i][j]=x;
  10. }
  11. scanf("%d",&m);
  12. f[0][0]=1;
  13. for(i=1;i<n;i++)
  14. f[i]=f[i-1],f[i][i]=1;
  15. while(m--){
  16. scanf("%d%d%d",&s,&l,&r);
  17. if(s==1){
  18. a^=f[r-1];
  19. if(l-1)a^=f[l-2];
  20. }else
  21. {
  22. scanf("%d",&p);
  23. c=a;
  24. if(l-1)c>>=l-2;
  25. c&=f[l[i]-1];
  26. if((c^b[p]).count())puts("NO");
  27. else puts("YES");
  28. }
  29. }
  30. }

  完。

帝都Day5——依旧是数据结构的更多相关文章

  1. 2019暑期金华集训 Day5 树上数据结构

    自闭集训 Day5 树上数据结构 前置知识 点分治 边分治 树链剖分 LCT Top Tree LCT时间复杂度 线段树每次查询是严格\(\log n\)的,然而splay维护连续段的时候,如果每次查 ...

  2. 帝都Day4(2)——数据结构

    黄姓dalao is coming! 一.栈: 基本常识略. 例题:铁轨 模拟,O(n), Usaco2006 Nov 题目略 做法:单调栈(续命栈?) n//数量 a[]//奶牛 for(int i ...

  3. 【10.10校内测试】【线段树维护第k小+删除】【lca+主席树维护前驱后驱】

    贪心思想.将a排序后,对于每一个a,找到对应的删除m个后最小的b,每次更新答案即可. 如何删除才是合法并且最优的?首先,对于排了序的a,第$i$个那么之前就应该删除前$i-1$个a对应的b.剩下$m- ...

  4. 正睿OI集训游记

    什么嘛....就是去被虐的... 反正就是难受就是了.各种神仙知识点,神仙题目,各式各样的仙人掌..... 但是还是学会了不少东西...... 应该是OI生涯最后一次集训了吧.... 这次的感言还是好 ...

  5. 帝都Day4(3)——还是数据结构

    可并堆 左偏树中 dist[x]=dist[rs[x]]+1 合并的时候,把权志较大的根作为根节点,把这棵树右子树和另一棵树合并. 说明白点:(上图描述有点问题) 设x表示根权值较大的左偏树,y表示根 ...

  6. 算法设计和数据结构学习_5(BST&AVL&红黑树简单介绍)

    前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm analysis in c++ (second ed ...

  7. 数据结构之链表C语言实现以及使用场景分析

    牢骚:本篇博客两个星期前已经存为草稿,鉴于发生一些糟糕的事情,今天才基本完成.本人6月份应届毕业生一枚,毕业后当天来到帝都,之后也非常顺利,面试了俩家公司都成功了.一家做C++方面电商ERP,一家做w ...

  8. Day5 - Python基础5 常用模块学习

    Python 之路 Day5 - 常用模块学习   本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shel ...

  9. Linux红黑树(一)——数据结构

    摘要 兹博文探讨四个重点:1.简单介绍红黑树:2.红黑树节点数据结构:3.红黑树节点中父节点指针域和自身节点颜色有机结合:4.定义红黑树和操作树节点父节点指针和节点颜色的接口,包括一系列宏和两个函数. ...

随机推荐

  1. 将session存入数据库,memcache的方法

    //存入数据库 <?phpif(!$con = mysql_connect('localhost','root','123456')){    die('连接数据库失败');}$link = m ...

  2. ONVIF测试方法及工具

    设备是否支持ONVIF验证1 ONVIF Test Tool安装1.1PC安装环境要求:装有Microsoft .Net Framework 3.5或以上版本.1.2安装源文件请见:ONVIF Con ...

  3. ACM学习历程—HDU 5534 Partial Tree(动态规划)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5534 题目大意是给了n个结点,让后让构成一个树,假设每个节点的度为r1, r2, ...rn,求f(x ...

  4. redis源码笔记 - redis-cli.c

    这份代码是redis的client接口,其和server端的交互使用了deps目录下的hiredis c库,同时,在这部分代码中,应用了linenoise库完成类似history命令查询.自动补全等终 ...

  5. [转]CSS3盒模型display:box详解

    时间:2014-02-25来源:网络作者:未知编辑:RGB display:box;box-flex是css3新添加的盒子模型属性,它的出现可以解决我们通过N多结构.css实现的布局方式.经典的一个布 ...

  6. 洛谷【P1601】A+B Problem(高精)

    题目传送门:https://www.luogu.org/problemnew/show/P1601 高精度加法板子.我们灵性地回忆一波小学学加法列竖式的场景(从\(6\)岁开始口算从未打过草稿的大佬请 ...

  7. C# 表达式树(Expression)

    c#中有Expression,即表达式. 通过Expression可以动态构造代码,并编译执行.  比如: 1.  创建参数表达式 :ParameterExpression numParam = Ex ...

  8. orcal数据库得连接必须用localhost,url中不要用127.0.0.1,不然无法连接

    orcal数据库得连接必须用localhost,url中不要用127.0.0.1,不然无法连接,

  9. 【转】 Pro Android学习笔记(六九):HTTP服务(3):HTTP POST MultiPart

    目录(?)[-] 建立测试环境 开发环境导入第三方JAR HTTP Post Multipart小例子 HTTP POST不仅可以通过键值对传递参数,还可以携带更为复杂的参数,例如文件.HTTP Po ...

  10. java代码简单练习

    总结: package com.ds; import java.awt.Color; import java.awt.FlowLayout; import javax.swing.JFrame; im ...