zoukankan      html  css  js  c++  java
  • 关于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/

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

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

  • 相关阅读:
    Layui 两个table 人员选择 多选
    iphone7 忘记密码 重装系统
    使用hql-统计连续登陆的三天及以上的用户
    azkaban群起/群停脚本
    Hive读取索引文件问题:select * 和select count(*)读取出来的行数不一致
    scala/java等其他语言从CSV文件中读取数据,使用逗号','分割可能会出现的问题
    hadoop3.1.3版本的secondaryNamenode的web界面不能显示的问题?
    启动kafka消费报错:WARN [Consumer clientId…] 1 partitions have leader brokers without a matching listener,…
    centos6和centos7的防火墙命令,以及它们的区别是是什么?
    kafka项目经验之如何进行Kafka压力测试、如何计算Kafka分区数、如何确定Kaftka集群机器数量
  • 原文地址:https://www.cnblogs.com/SutsuharaYuki/p/11206652.html
Copyright © 2011-2022 走看看