2019 計蒜之道 初賽 第五場 浪潮集團的「超級大樹」

 

有助於瞭解樹的結構node

 

Pro:
https://nanti.jisuanke.com/t/39451

Sol:
點的總數太大,沒法存儲

實際上使用過的點很少

1.對於未使用過的點,不進行建立
樹上的遍歷,求出被刪除的點的總數

相似思想:線段樹動態開點

對於每一個點,從根節點到該點之間的全部的點被建立,當前樹上的全部被建立的點的總數爲D
D<=kQ
每次查詢,添加或刪除 logD
樹上的遍歷 D


map/unordered_map
紅黑樹
查找,添加或刪除元素 log(D)


vector
元素從小到大排序
找到添加或刪除的位置 二分 lower_bound log(D)
而後添加或刪除元素 log(D)
查找元素 log(D)


數組
添加或刪除元素 D    最差狀況是每次處理的都是編號最小(編號從小到大排序)的點,這裏D較小,能夠接受
查找元素 log(D)



2.對於使用過的點,放在vector/set(這裏全部刪除的點的編號都不一樣)/map等stl容器中,數組也行
對於每一個刪除的點,尋找祖先節點,看是否存在祖先節點被刪去,若是是,這個刪除的點不起做用(這個點的子樹包含在祖先節點的子樹內)

對於全部點,訪問的點爲從該點向上,直到第一個存在的點或根節點
重複的路徑中的點沒有被訪問屢次

每次查詢,添加或刪除 logD
尋找操做 D



對於M叉樹的M爲1,k<=1e18
不能使用上述方法
當M=1,樹爲鏈式結構,
只需記錄被刪除的點中編號最大的點便可
對於M>=1,k<=log(x+eps)/log(2) <64

ios

 

way1數組

tree not building not existing pointui

vectorthis

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iostream>
 8 using namespace std;
 9 #define ll long long
10 #include <vector>
11 
12 const double eps=1e-8;
13 const ll inf=1e9;
14 const ll mod=1e9+7;
15 const int maxn=(5e2+10)*64;///
16 
17 struct node
18 {
19     ll nex[2],cond;
20 }tr[maxn];
21 
22 vector<ll> vec;
23 
24 ll cnt[100],m,maxdep,ind,pos;
25 
26 ll dfs(ll d,ll dep)
27 {
28     ll i;
29     if (tr[d].cond==1)
30         return cnt[maxdep-dep];
31     ll sum=0;
32     for (i=0;i<2;i++)
33         if (tr[d].nex[i])
34             sum+=dfs(tr[d].nex[i],dep+1);
35     return sum;
36 }
37 
38 void build(ll x)
39 {
40     if (x!=0)
41     {
42         build((x-1)/m);
43         if (!tr[pos].nex[(x-1)%m])
44             tr[pos].nex[(x-1)%m]=++ind;
45         pos=tr[pos].nex[(x-1)%m];
46     }
47 }
48 
49 int main()
50 {
51     ll q,opt,i,x;
52     scanf("%lld%lld%lld",&m,&maxdep,&q);
53     if (m!=1)
54     {
55         x=1;
56         for (i=1;i<=maxdep;i++)
57         {
58             cnt[i]=cnt[i-1]+x;
59             x*=m;
60         }
61     }
62 
63     while (q--)
64     {
65         scanf("%lld%lld",&opt,&x);
66         ///remove
67         if (opt==1)
68         {
69             if (m==1)
70                 vec.insert(lower_bound(vec.begin(),vec.end(),x) , x);
71             else
72             {
73                 pos=0;
74                 build(x);
75                 tr[pos].cond=1;
76             }
77         }
78         ///add
79         else
80         {
81             if (m==1)
82                 vec.erase(lower_bound(vec.begin(),vec.end(),x));
83             else
84             {
85                 pos=0;
86                 build(x);
87                 tr[pos].cond=0;
88             }
89         }
90         if (m==1)
91             printf("%lld\n",vec.empty()?maxdep:vec[0]);
92         else
93             printf("%lld\n",cnt[maxdep]-dfs(0,0));
94     }
95     return 0;
96 }

 

way2spa

visit ancestorcode

setblog

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iostream>
 8 using namespace std;
 9 #define ll long long
10 #include <set>
11 
12 const double eps=1e-8;
13 const ll inf=1e18;
14 const ll mod=1e9+7;
15 const int sexn=(5e2+10)*64;///
16 
17 set<ll> se;
18 
19 ll cnt[100],m,maxdep;
20 
21 int main()
22 {
23     ll q,opt,i,x,xx,sum;
24     bool vis;
25     set<ll>::iterator j;
26     scanf("%lld%lld%lld",&m,&maxdep,&q);
27     if (m!=1)
28     {
29         x=1;
30         for (i=1;i<=maxdep;i++)
31         {
32             cnt[i]=cnt[i-1]+x;
33             x*=m;
34         }
35     }
36 
37     while (q--)
38     {
39         scanf("%lld%lld",&opt,&x);
40         ///remove
41         if (opt==1)
42             se.insert(x);
43         ///add
44         else
45             ///must has this element, not need to judge if xxx!=yyy.end()
46             ///oterwise if no this element, wrong!
47             se.erase(se.find(x));
48 
49         if (m==1)
50         {
51             if (se.empty())
52                 printf("%lld\n",maxdep);
53             else
54             {
55                 x=inf;
56                 for (j=se.begin();j!=se.end();j++)
57                     x=min(x,*j);
58                 printf("%lld\n",x);
59             }
60         }
61         else
62         {
63             sum=cnt[maxdep];
64             for (j=se.begin();j!=se.end();j++)
65             {
66                 x=*j;
67                 xx=x;
68                 vis=1;
69                 while (x)
70                 {
71                     x=(x-1)/m;
72                     if (se.find(x)!=se.end())
73                     {
74                         vis=0;
75                         break;
76                     }
77                 }
78                 if (vis)
79                     sum-=cnt[maxdep+1-(lower_bound(cnt,cnt+maxdep+1,xx+1)-cnt)];
80 
81             }
82             printf("%lld\n",sum);
83         }
84     }
85     return 0;
86 }

 

map排序

這裏用map,第二維就是不必的。element

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iostream>
 8 using namespace std;
 9 #define ll long long
10 #include <map>
11 
12 const double eps=1e-8;
13 const ll inf=1e18;
14 const ll mod=1e9+7;
15 const int maxn=(5e2+10)*64;///
16 
17 map<ll,ll> ma;
18 
19 ll cnt[100],m,maxdep;
20 
21 int main()
22 {
23     ll q,opt,i,x,xx,sum;
24     bool vis;
25     map<ll,ll>::iterator j;
26     scanf("%lld%lld%lld",&m,&maxdep,&q);
27     if (m!=1)
28     {
29         x=1;
30         for (i=1;i<=maxdep;i++)
31         {
32             cnt[i]=cnt[i-1]+x;
33             x*=m;
34         }
35     }
36 
37     while (q--)
38     {
39         scanf("%lld%lld",&opt,&x);
40         ///remove
41         if (opt==1)
42             ma[x]=1;
43         ///add
44         else
45             ///must has this element, not need to judge if xxx!=yyy.end()
46             ///oterwise if no this element, wrong!
47             ma.erase(ma.find(x));
48         if (m==1)
49         {
50             if (ma.empty())
51                 printf("%lld\n",maxdep);
52             else
53             {
54                 x=inf;
55                 for (j=ma.begin();j!=ma.end();j++)
56                     x=min(x,j->first);
57                 printf("%lld\n",x);
58             }
59         }
60         else
61         {
62             sum=cnt[maxdep];
63             for (j=ma.begin();j!=ma.end();j++)
64             {
65                 x=j->first;
66                 xx=x;
67                 vis=1;
68                 while (x)
69                 {
70                     x=(x-1)/m;
71                     if (ma.find(x)!=ma.end())
72                     {
73                         vis=0;
74                         break;
75                     }
76                 }
77                 if (vis)
78                     sum-=cnt[maxdep+1-(lower_bound(cnt,cnt+maxdep+1,xx+1)-cnt)];
79 
80             }
81             printf("%lld\n",sum);
82         }
83     }
84     return 0;
85 }

 

數組

仍是用vector吧。。。

相關文章
相關標籤/搜索