关于G

https://vjudge.net/contest/310809#problem/G

只是一些瞎想

没学过线段树,不会区间更新,不会做维护(我就是一条咸鱼
花了五分钟在网上看了一下线段树的思想,大概明白了怎么个用法,但是没有背模板也不会写

所以考虑用树状数组
用二维数组叠成线段树的样子

简单讲下想法:
核心:二维数组写线段树
    第1层是目标数列;
    第2层存储每相邻2项之和,第3层存储每相邻4项之和,以此类推...
    第n层存储每相邻2^n项之和;
  (题目要求1≤n,q≤100000不超过2^17,17*100000的矩阵可以完成)

一个简单的例子
16 100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
add 1 12
12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 8 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0
 4 0 0 0 4 0 0 0 4 0 0 0 0 0 0 0
 2 0 2 0 2 0 2 0 2 0 2 0 0 0 0 0
 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0

  每次 add 操作,对a数组对应元素+1,

  满足a[i]==b[i]则置零, 找到tree数组底层对应元素,从该结点到根节点的路径都标记上+1;
  访问路径结点通过数组下标的计算实现。

  query操作麻烦一些,
  一方面要判断能取到的最大段,另一方面要定位端点,把剩下的部分继续拆分。
  通过一个l,r分别除一个整数div = 2^n,找到当前端点所在的区段,
  div从上限开始,每次减半,
  若可以取到当前大小的整段,把当前整段的权值加到res,并记录下断电,
  对裁剪后两边的段进行相同操作,

因为区段(l,r)是连续的,每次断开断点为2^n,所以当前状态最多有两个不相接段;
另外当l,r为2^n点时可以有简化计算。

很遗憾的是这段代码仅通过了样例和部分测试组,所以并没有算过题

  并且这种实现方法非常蹩脚 debug基本靠笔算
  所以以后肯定老老实实背模板,也不会这么瞎鸡乱搞了

绿皮车代码仅供娱乐

 1 #include <iostream>
 2 using namespace std;
 3 typedef long long ll;
 4 
 5 int sum[17][100006] = {0};
 6 int a[100006] = {0};
 7 int b[100006] = {0};
 8 char tell[6] = {0};
 9 
10 int main(){
11     int n , q ;
12     int l , r ;
13     cin >> n >> q;
14     for (int i = 0;i<n;i++){
15         cin >> b[i];
16     }//建树,完成输入
17     while(q--){
18         cin >> tell >> l >> r;
19         if(tell[0]=='a'){//add操作
20             for(int i = l-1;i<r;i++){
21                 a[i]++;//对a累加
22                 if (a[i]>=b[i]){//a累加到b时
23                     for(int j = 0,k = 1;j<17;j++){
                //该节点到根节点路径上标记+1 24 sum[16-j][i/k*k]++; 25 k*=2; 26 } 27 a[i] = 0;//a置零 28 } 29 } 30 } 31 else if(tell[0]=='q'){//query操作 32 bool s1 = 0;//端点是否截断在2^n位置 33 int res = 0;//结果 34 int l1 = -1 , r1 = -1;//拆分后用的新断点 35 for(int i = 0,div= 65536;i<17;i++){
                //div从2^16开始,每次减半 36 if(l1==-1 && r1==-1){
                //判断是否被截取过 37 if(l/div==0 && l/div+1 < r/div){
//能截出当前最大段时 38 l1 = l/div+1; 39 r1 = r/div; 40 for(int j = l1; j<r1 ; j++){ 41 res+=sum[i][j*div]; 42 } 43 } 44 else if(l/div!=0 && l/div < r/div) { 45 l1 = l/div; 46 r1 = r/div; 47 for(int j = l1; j<r1 ; j++){ 48 res+=sum[i][j*div]; 49 } 50 } 51 else if( (l-1)%div==0){ 52 l1 = l/div; 53 r1 = r/div; 54 for(int j = l1; j<r1 ; j++){ 55 res+=sum[i][j*div]; 56 } 57 s1 = 1; 58 }//求和,移动断点,完成截取 59 } 60 else{//已经截成了两段时 61 l1 *=2 ; r1*=2; 62 if(l/div==0 && l/div+1 < l1){ 63 for(int j = l/div+1 ; j<l1 ; j++){ 64 res+=sum[i][j*div]; 65 } 66 l1 = l/div+1; 67 } 68 else if(l/div!=0 && l/div < r/div) { 69 for(int j = l/div ; j<l1 ; j++){ 70 res+=sum[i][j*div]; 71 } 72 l1 = l/div; 73 } 74 else if( (l-1)%div==0){ 75 if(s1 == 1); 76 else{ 77 for(int j = l/div; j<l1 ; j++){ 78 res+=sum[i][j*div]; 79 } 80 s1 = 1; 81 } 82 }//完成左边段截取 83 if(r1 < r/div){ 84 for(int j = r1 ; j<r/div ; j++){ 85 res+=sum[i][j*div]; 86 } 87 r1 = r/div; 88 } 89 }//完成右边段截取 90 div >>= 1;//div减半 91 } 92 cout<<res<<endl; 93 } 94 } 95 }

带debug输出的版本,供自己以后心情好了翻出来改

  1 #include <iostream>
  2 #include <iomanip>
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 
  7 int sum[17][100006] = {0};
  8 int a[100006] = {0};
  9 int b[100006] = {0};
 10 char tell[6] = {0};
 11 
 12 int main()
 13 {
 14     int n , q ;
 15     int l , r ;
 16     cin >> n >> q;
 17     for (int i = 0;i<n;i++)
 18     {
 19         cin >> b[i];
 20     }
 21     while(q--)
 22     {
 23         cin >> tell >> l >> r;
 24         if(tell[0]=='a')
 25         {
 26             for(int i = l-1;i<r;i++)
 27             {
 28                 a[i]++;
 29                 if (a[i]>=b[i])
 30                 {
 31                     for(int j = 0,k = 1;j<17;j++)
 32                     {
 33                         sum[16-j][i/k*k]++;
 34                         k*=2;
 35                     }
 36                     a[i] = 0;
 37                 }
 38                     
 39             }
 40             for(int j = 0;j<17;j++)                  //
 41                     {
 42                         for(int k = 0;k<16;k++)
 43                             cout<<setw(2)<<sum[j][k]<<" ";
 44                         cout<<endl;
 45                     }
 46                     
 47         }
 48         else if(tell[0]=='q')
 49         {
 50             bool s1 = 0;
 51             int res = 0;
 52             int l1 = -1 , r1 = -1;
 53             for(int i = 0,div= 65536;i<17;i++)
 54             {
 55                 if(l1==-1 && r1==-1)
 56                 {
 57                     if(l/div==0 && l/div+1 < r/div)
 58                     {
 59                         l1 = l/div+1;    
 60                         r1 = r/div;        
 61                         for(int j = l1; j<r1 ; j++)
 62                         {
 63                             res+=sum[i][j*div];
 64                         }
 65                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" A1"<<endl;//
 66                     }
 67                     else if(l/div!=0 && l/div < r/div) 
 68                     {
 69                         l1 = l/div;    
 70                         r1 = r/div;        
 71                         for(int j = l1; j<r1 ; j++)
 72                         {
 73                             res+=sum[i][j*div];
 74                         }
 75                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" A2"<<endl;//
 76                     }
 77                     else if( (l-1)%div==0)
 78                     {
 79                         l1 = l/div;    
 80                         r1 = r/div;    
 81                         for(int j = l1; j<r1 ; j++)
 82                         {
 83                             res+=sum[i][j*div];
 84                         }
 85                         s1 = 1;
 86                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" B"<<endl;//
 87                     }
 88                 }
 89                 else
 90                 {
 91                     l1 *=2 ; r1*=2;
 92                     if(l/div==0 && l/div+1 < l1)                        
 93                     {
 94                         for(int j = l/div+1 ; j<l1 ; j++)
 95                         {
 96                             res+=sum[i][j*div];
 97                         }
 98                         l1 = l/div+1;
 99                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" L11"<<endl;//
100                     }
101                     else if(l/div!=0 && l/div < r/div) 
102                     {
103                         for(int j = l/div ; j<l1 ; j++)
104                         {
105                             res+=sum[i][j*div];
106                         }
107                         l1 = l/div;
108                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" L12"<<endl;//
109                     }
110                     else if( (l-1)%div==0)
111                     {
112                         if(s1 == 1);
113                         else
114                         {    
115                             for(int j = l/div; j<l1 ; j++)
116                             {
117                                 res+=sum[i][j*div];
118                             }
119                             s1 = 1;
120                             //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" L2"<<endl;//
121                         }
122                         
123                     }
124                     
125                     if(r1 < r/div)
126                     {
127                         for(int j = r1 ; j<r/div ; j++)
128                         {
129                             res+=sum[i][j*div];
130                         }
131                         r1 = r/div;
132                         //cout<<"!!"<<res<<' '<<div<<" "<<i<<" "<<l1<<" "<<r1<<" R"<<endl;//
133                     }
134                 }
135                 div >>= 1;
136             }
137             cout<<res<<endl;
138         }
139     }
140 }
View Code

作者:YukiRinLL

出处:YukiRinLL的博客--https://www.cnblogs.com/SutsuharaYuki/

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但请保留该声明。

原文地址:https://www.cnblogs.com/SutsuharaYuki/p/11206652.html