暑假集训0811

利用树的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

 

你可能感兴趣的:(暑假集训0811)