树(Persistent Bookcase,cf 707d)

来源:互联网 发布:mac os 10.12 原版 编辑:程序博客网 时间:2024/06/05 18:24

觉得无非就是存起来或者原路找回去。

存起来需要太多的空间,肯定不行的。

讲道理,原路找回去好难编程实现,一会往前一会往后,而且多走了很多路。

这就是为什么要用某种数据结构建模的原因吧。

真的能显著降低编程难度,而且思路十分清晰。

看到这种回溯的东西,应该要想到树的。。。

用了树之后访问顺序有所变化,但这反而少走了很多路。

建模思想还不够吧。。。


n个点的多叉树,必有n-1条边。

dfs经常会出现访问顺序不如意的情况,那就记录下来,然后再循环一遍输出吧。

老是希望一遍dfs搞定所有问题,有点钻牛角尖了,这样只会使编程复杂度增加很多,思路极不清晰,很容易出错,然而效率却没有显著的提升,不值。比赛中编程复杂度也是很重要的参考。


参考 http://www.cnblogs.com/Coolxxx/p/5792237.html


他没有用线段树。

对比:

查询都是O(1)。

单点更新他是O(1),我是log(n*m)。

区间更新他是O(m),我是log(n*m)。

跑了一下其实差不多快。

线段树的优点是区间更新与查询快,但是单点更新慢。


速度差别不大的主要原因是

1、每次查询都是查全部,因此线段树最大的优势没了。

2、每次区间更新的长度都很短,因此线段树次要的优势被严重压制。

3、单点更新非常多,线段树劣势被放大。
最后就差不多快了。


这道题的核心是建树与dfs吧。


我的代码

#include<stdio.h>#include<vector>#define maxn 1000010using namespace std;int tree[maxn<<2];bool add[maxn<<2];bool D(int l,int r,int now,int a,int b){    if(l==r)    {        bool deng=tree[now]==b;        tree[now]=b;        return deng;    }    int m=(l+r)>>1;    int ls=now<<1;    int rs=ls|1;    if(add[now])    {        add[ls]^=1;        add[rs]^=1;        add[now]=0;        tree[ls]=m-l+1-tree[ls];        tree[rs]=r-m-tree[rs];        tree[now]=tree[ls]+tree[rs];    }    bool deng;    if(a<=m) deng=D(l,m,ls,a,b);    else deng=D(m+1,r,rs,a,b);    tree[now]=tree[ls]+tree[rs];    return deng;}void Q(int l,int r,int now,int ql,int qr){    if(l>qr||r<ql) return;    if(ql<=l&&qr>=r)    {        add[now]^=1;        tree[now]=r-l+1-tree[now];        return;    }    int m=(l+r)>>1;    int ls=now<<1;    int rs=ls|1;    if(add[now])    {        add[ls]^=1;        add[rs]^=1;        add[now]=0;        tree[ls]=m-l+1-tree[ls];        tree[rs]=r-m-tree[rs];        tree[now]=tree[ls]+tree[rs];    }    Q(l,m,ls,ql,qr);    Q(m+1,r,rs,ql,qr);    tree[now]=tree[ls]+tree[rs];}void print(int l,int r,int now){    int m=(l+r)>>1;    int ls=now<<1;    int rs=ls|1;    if(add[now])    {        add[ls]^=1;        add[rs]^=1;        add[now]=0;        tree[ls]=m-l+1-tree[ls];        tree[rs]=r-m-tree[rs];        tree[now]=tree[ls]+tree[rs];    }    printf("%d\n",tree[1]);}struct op{    int id;    int a,b;    vector<int>next;    op(int A,int B,int C):id(A),a(B),b(C){}};int n,m,q;vector<op>vec;void dfs(op now){    bool deng;    switch (now.id)    {    case 1:        deng=D(1,n*m,1,(now.a-1)*m+now.b,1);        break;    case 2:        deng=D(1,n*m,1,(now.a-1)*m+now.b,0);        break;    case 3:        Q(1,n*m,1,(now.a-1)*m+1,now.a*m);    }    print(1,n*m,1);    for(unsigned int i=0;i<now.next.size();i++)        dfs(vec[now.next[i]]);    switch (now.id)    {    case 1:        if(!deng)            D(1,n*m,1,(now.a-1)*m+now.b,0);        break;    case 2:        if(!deng)            D(1,n*m,1,(now.a-1)*m+now.b,1);        break;    case 3:        Q(1,n*m,1,(now.a-1)*m+1,now.a*m);    }}void init(){    scanf("%d %d %d",&n,&m,&q);    int id,a,b;    vec.push_back(op(0,0,0));    while(q--)    {        scanf("%d",&id);        switch (id)        {        case 1:        case 2:            scanf("%d %d",&a,&b);            vec.push_back(op(id,a,b));            break;        case 3:        case 4:            scanf("%d",&a);            vec.push_back(op(id,a,0));            break;        }    }    for(unsigned int i=1;i<vec.size();i++)    {        if(vec[i].id==4)            vec[vec[i].a].next.push_back(i);        else            vec[i-1].next.push_back(i);    }    for(unsigned int i=0;i<vec[0].next.size();i++)        dfs(vec[vec[0].next[i]]);}int main(){    init();    return 0;}


0 0
原创粉丝点击