树的dfs序 && 系统栈 && c++ rope

利用树的dfs序解决问题:

就是dfs的时候记录每个节点的进入时间和离开时间,这样一个完整的区间就是一颗完整的树,就转化成了区间维护的问题。

比如hdu3887 本质上是一个求子树和的问题

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <stack>
  7 //#pragma comment(linker,"/STACK:1024000000,1024000000")
  8 using namespace std;
  9 #define MAXN (200000+10)
 10 #define lowbit(i) (i&(-i))
 11 int n,m;
 12 struct BIT{
 13     int t[MAXN];
 14     BIT(){memset(t,0,sizeof(t));}
 15     void init(){memset(t,0,sizeof(t));}
 16     int _query(int a){
 17         int ans=0;
 18         for (int i=a;i>=1;i-=lowbit(i))    ans+=t[i];
 19         return ans;
 20     }
 21     void modify(int a,int x){
 22         for (int i=a;i<=n;i+=lowbit(i))    t[i]+=x;
 23     }
 24     
 25     int query(int a,int b){
 26         return _query(b)-_query(a-1);
 27     }
 28 }T;
 29 int timemark;
 30 int intime[MAXN],outime[MAXN];
 31 int data[MAXN];
 32 int f[MAXN];
 33 int head[MAXN],next[MAXN],e[MAXN],countside;
 34 void buildside(int a,int b){
 35     e[countside]=b;
 36     next[countside]=head[a];
 37     head[a]=countside++;
 38 }
 39 /*
 40 void dfs(int x,int fa){
 41     intime[x]=timemark++;
 42     for (int i=head[x];i>0;i=next[i]){
 43         if (e[i]!=fa){
 44             dfs(e[i],x);
 45         }
 46     }
 47     outime[x]=timemark++;
 48 }
 49 */
 50 
 51 stack<int> s;
 52 bool instack[MAXN];
 53 void dfs(int root){
 54     memset(instack,false,sizeof instack);
 55     s.push(root);
 56     intime[root]=timemark++;
 57     instack[root]=true;
 58     while (!s.empty()){
 59         bool loop=false;
 60         int now=s.top();
 61         for (int i=head[now];i>0;i=next[i]){
 62             if (!instack[e[i]]){
 63                 s.push(e[i]);
 64                 instack[e[i]]=true;
 65                 intime[e[i]]=timemark++;
 66                 loop=true;
 67                 break;
 68             }
 69         }
 70         if (loop)    continue;
 71         s.pop();
 72         outime[now]=timemark++;
 73     }
 74 }
 75 
 76 int main (int argc, char *argv[])
 77 {
 78     int p;
 79     int a,b;
 80     char cmd[10];
 81     
 82     while (1){
 83         scanf("%d%d",&n,&p);
 84     
 85         if (n==0 && p==0)    break;
 86     
 87         memset(head,0,sizeof head);
 88         memset(next,0,sizeof next);
 89         memset(e,0,sizeof e);    
 90     
 91         countside=1;
 92         for (int i=1;i<=n-1;i++){
 93             scanf("%d%d",&a,&b);
 94             buildside(a,b);
 95             buildside(b,a);
 96         }
 97     
 98         timemark=1;
 99         dfs(p);
100     
101     
102         /*for (int i=1;i<=n;i++)    cout<<intime[i]<<" "<<outime[i]<<endl;*/
103     
104         int N=n;
105         n=n*2;
106         T.init();
107         for (int i=1;i<=n;i++){
108             data[i]=1;
109             T.modify(i,1);
110         }
111     
112         for (int i=N;i>=1;i--){
113             f[i]=(T.query(intime[i],outime[i])-2)/2;
114             T.modify(intime[i],-1);
115             T.modify(outime[i],-1);
116         }
117     
118         for (int i=1;i<=N-1;i++)    printf("%d ",f[i]);
119         printf("%d\n",f[N]);
120     }
121     return 0;
122 }
View Code

直接dfs爆栈了,所以我写了一个手工栈。结果后来发现这样就行了QAQ

1 #pragma comment(linker,"/STACK:100000000,100000000")

WTF。。。涨姿势了

 

再就是对于那种复杂的序列操作问题,比如文本编辑器,我发现了C++ 里还有rope这个东西。当然这不是标准STL的,这是SGI STL的一部分。但是如果比赛的时候能用就爽了。。。不管怎么说先记录一下,平时也是蛮实用的。

rope就是一个能支持各种操作的序列,crope就是rope的字符串版本。rope自带各种炫酷的功能,时间各种logn,就连空间也超小。据说内部实现的是一个可持久化的平衡数并且加上共享节点。Orz

NOI 的那道文本编辑器

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <ext/rope>
 6 using namespace std;
 7 using namespace __gnu_cxx;
 8 crope List;
 9 int n,now,k;
10 char s[2500005];
11 int main()
12 {
13     char cmd[25];
14     int i;
15     for (scanf("%d",&n);n--;)
16     {
17         scanf("%s",cmd);
18         if (cmd[0]=='M') scanf("%d",&now);
19         else if (cmd[0]=='I')
20         {
21             scanf("%d%*c",&k);
22             for (i=0;i<k;i++) do
23             {
24                 scanf("%c",&s[i]);
25             }while(s[i]=='\n');
26             s[k]=0;
27             List.insert(now,s);
28         }
29         else if (cmd[0]=='D')
30         {
31             scanf("%d",&k);
32             List.erase(now,k);
33         }
34         else if (cmd[0]=='G')
35         {
36             scanf("%d",&k);
37             List.copy(now,k,s);
38             s[k]=0;
39             puts(s);
40         }
41         else if (cmd[0]=='P') now--;
42         else now++;
43     }
44     return 0;
45 }
View Code

 

posted @ 2014-08-12 08:31  wsc500  阅读(419)  评论(0编辑  收藏  举报