线段树、树状数组
A 樹狀數組: 1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include <string.h>
5 using namespace std;
6 // 1h / 10min
7 const int maxn = 32001;
8 int c[maxn],ans[maxn]; // c[i] : 以i為橫坐標的星星左側和下側星星的個數, ans[i] : 某層的星星的個數
9 int x,y;
10 int lowbit(int x)
11 {
12 return x&(-x);
13 }
14 int sum(int x) // 計算橫坐標為x的星星的level
15 {
16 int s = 0;
17 for (x ; x > 0 ; x -=lowbit(x))
18 {
19 s += c[x];
20 }
21 return s;
22 }
23 void insert(int x)
24 {
25 for (x ; x <= maxn ; x += lowbit(x))
26 {
27 c[x]++;
28 }
29 }
30 int main()
31 {
32 int n;
33 while (scanf("%d",&n)!=EOF)
34 {
35 memset(c,0,sizeof(c));
36 memset(ans,0,sizeof(ans));
37 for (int i=0;i<n;i++)
38 {
39 scanf("%d%d",&x,&y); x++;// 橫坐標整體往右移動一位
40 ans[sum(x)]++;
41 insert(x);
42 }
43 for (int i=0;i<n;i++)
44 cout << ans[i] << endl;
45 }
46
47 }
?
樹狀數組: https://www.cnblogs.com/hsd-/p/6139376.html https://blog.csdn.net/flushhip/article/details/79165701 https://blog.csdn.net/zheng0518/article/details/51119042 https://blog.csdn.net/kkkkahlua/article/details/76785265 https://blog.csdn.net/moep0/article/details/52770728 題目解析:https://blog.csdn.net/zhanghaoxian1/article/details/74275951- 有一點明白但還是不是很懂怎么轉換的過程,再重新順一遍過程。
線段樹
- 自學困難的知識的時候,不要有畏難心理。所有的難知識都可以通過一定的方法,掰碎了一點一點消化吸收的,我只需要一個程序一個程序地編寫。在編寫的過程中,遇到不清楚的知識點,一定要記下來!并且回去反復思考總結!我的問題總是反反復復的出現,一如我踩過的坑,下次遇到這個坑的時候還是義無反顧地跳進去,這就是我最大的問題!不總結!犯重復的錯誤!而且你要有時刻準備好的狀態,不要畏畏縮縮的,大家都是這么過來的,慢慢來,還有兩個月的時間,每天做五道題,你會超越絕大多數的人。
- 創建線段樹和中序遍歷線段樹的代碼寫不對,爆出segment fault這等高級段錯誤,與結構體、指針、構造函數有關。
- 菜鳥都能理解的線段樹
?
敵兵布陣
詳細的線段樹入門+題目講解(提交時超時了) 不超時答案 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include <string> 5 #include <string.h> 6 using namespace std; 7 // 1h 35 8 // (step<<1)+1 括號必須加,優先級問題 9 const int maxn = 1000000; // 數組長度定義為多少?? 10 struct node 11 { 12 int left,right,value; 13 }tree[maxn]; 14 /* 15 void build(int l,int r,int step) 16 { 17 // 1. 第step個結點的賦值 18 tree[step].left = l; 19 tree[step].right = r; 20 tree[step].value = 0; 21 // cout << "結點:"<< step << ",左:" << l << ",右:" << r<< endl; 22 // 2. 遞歸邊界 23 if (l == r) 24 return ; 25 // 3. 一分為2,繼續遞歸創建子樹 26 int mid = (l+r)>>1; // 右移1位 = 除以2, 為什么不直接除以2 ?? 27 build(l,mid,step<<1); // step * 2 左子樹 28 build(mid+1,r,(step<<1)+1); // step * 2 + 1右子樹 29 } 30 */ 31 void init(int n)//新建一個線段樹 32 { 33 int i,k; 34 for(k = 1; k<n; k<<=1); 35 for(i = k; i<2*k; i++) 36 { 37 tree[i].left = tree[i].right = i-k+1; 38 tree[i].value = 0; 39 } 40 for(i = k-1; i>0; i--) 41 { 42 tree[i].left = tree[2*i].left; 43 tree[i].right = tree[2*i+1].right; 44 tree[i].value = 0; 45 } 46 } 47 void update(int l,int r,int value,int step) 48 { 49 tree[step].value += value; 50 // cout <<"結點:"<< step << "加上" << value <<endl; 51 // 遞歸邊界 52 if (tree[step].left == tree[step].right ) // 更新到葉子結點 , 為什么不能寫成left = l && right = r ?? 53 { 54 // tree[step].value = value; 55 // cout << "step:"<< step << ",l:" << l << ",r:" << r<< value <<endl; 56 return; 57 } 58 int mid = (tree[step].left + tree[step].right) >> 1; 59 if (r <= mid) 60 { 61 // 線段在根節點的左半區間 62 update(l,r,value,step<<1); 63 }else if (l > mid) // 右半區間 64 { 65 update(l,r,value,(step<<1)+1); 66 }else 67 { 68 // l,r 跨越了mid,分別更新 69 update(l,mid,value,step<<1); 70 update(mid+1,r,value,(step<<1)+1); 71 } 72 } 73 int query(int l,int r,int step) // 求 l - r的和 ???? 74 { 75 // if (tree[step].left == tree[step].right) 76 if(l == tree[step].left && r == tree[step].right) 77 { 78 // printf("返節點%d的值%d\n",step,tree[step].value); 79 return tree[step].value; 80 } 81 int mid = (tree[step].left + tree[step].right) >> 1; 82 if(r <= mid) 83 { 84 // printf("結點:%d 查詢%d到%d \n",step,l,r); 85 return query(l, r, step<<1); 86 } 87 if(l > mid) 88 { 89 // printf("結點:%d 查詢%d到%d \n",step,l,r); 90 return query(l, r, (step<<1)+1); 91 } 92 else 93 { 94 // printf("結點:%d 查詢%d到%d 和%d %d \n",step,l,mid,mid+1,r); 95 return query(l, mid, step<<1) + query(mid+1, r, (step<<1)+1); 96 } 97 } 98 int main() 99 { 100 int t,n,ai,a,b; 101 char order[10]; 102 scanf("%d",&t); 103 for (int j = 1;j<=t;j++) 104 { 105 scanf("%d",&n); 106 // build(1,n,1); 107 init(n); 108 // 依次更新每個營地的人數值 109 for (int i=1;i<=n;i++) 110 { 111 scanf("%d",&ai); 112 update(i,i,ai,1); 113 } 114 printf("Case %d:\n",j); 115 while (scanf("%s",order)!=EOF && strcmp(order,"End")!=0) 116 { 117 cin >> a >> b; 118 if (strcmp(order,"Add") == 0) 119 { 120 update(a,a,b,1); 121 } 122 if (strcmp(order,"Sub") == 0) 123 { 124 update(a,a,-b,1); 125 } 126 if (strcmp(order,"Query")==0) 127 { 128 cout << query(a,b,1) << endl; 129 } 130 } 131 } 132 }?
- 我他喵的研究了三個小時之后終于accept而且我好像看懂其中的原理了我很開心。Hhhhhh這大概就是計算機的女人絕不認輸的精神吧!
C I hate it
- 改了改update和query
?
但是看到有在build部分修改函數的: 線段樹 最大最小模板D just a hook
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include <string> 5 #include <string.h> 6 using namespace std; 7 8 const int maxn = 1000000; 9 struct node 10 { 11 int left,right,value; 12 }tree[maxn]; 13 14 void build(int n) 15 { 16 int i,k; 17 for (k=1;k<n;k=k<<1); 18 for (i=k;i<k*2;i++) 19 { 20 tree[i].left = tree[i].right = i-k+1;tree[i].value = 0; 21 // printf("結點:%d,左邊:%d,右邊:%d\n",i,i-k+1,i-k+1); 22 } 23 for (i=k-1;i>0;i--) 24 { 25 tree[i].left = tree[2*i].left; 26 tree[i].right = tree[2*i+1].right; 27 tree[i].value = 0; 28 // printf("結點:%d,左邊:%d,右邊:%d\n",i,tree[i<<1].left,tree[(i<<1)+1].right); 29 } 30 } 31 32 void update(int l,int r,int value ,int step) 33 { 34 tree[step].value += value; 35 // printf("結點:%d,左邊:%d,右邊:%d,value:%d\n",step,tree[step].left,tree[step].right,tree[step].value); 36 if (tree[step].left == tree[step].right) 37 { 38 return ; 39 } 40 int mid = (tree[step].left+tree[step].right)>>1; 41 if (r <= mid) 42 update(l,r,value,step<<1); 43 else if (l>mid) 44 update(l,r,value,(step<<1)+1); 45 else 46 { 47 update(l,mid,value,step<<1); 48 update(mid+1,r,value,(step<<1)+1); 49 } 50 } 51 int main() 52 { 53 int t,n,q,a,b,c,x; 54 scanf("%d",&t); 55 for (int i = 1;i<=t;i++) 56 { 57 scanf("%d%d",&n,&q); // stick number & oper number 58 build(n); 59 for (int g=1;g<=n;g++) 60 update(g,g,1,1); 61 62 for (x=1;x<n;x=x<<1); 63 for (int j=1;j<=q;j++) 64 { 65 scanf("%d%d%d",&a,&b,&c); // a-b 修改mental kind 66 for (int k = a;k<=b;k++) 67 update(k,k,c-tree[x+k-1].value,1); 68 } 69 printf("Case %d:The total value of the hook is %d\n",i,tree[1].value); 70 71 72 } 73 74 }?
- 區間更新 = 循環+每個點的單點更新 = Time limited exceed
轉載于:https://www.cnblogs.com/twomeng/p/9509823.html
總結
- 上一篇: qq群t人php,QQ群机器人,自动加人
- 下一篇: xss和csrf