2019CCPC厦门站D. Zayin and Forest(树状数组 手写哈希表)

简介: 2019CCPC厦门站D. Zayin and Forest(树状数组 手写哈希表)

题意:

定义B ( x )表示x的二进制形式中1的个数,F ( x ) = m i n ( y ∣ y > x & B ( y ) < = B ( x ) )

给出n,对于x < = n,如果F ( x ) < = n,那么x的父节点是F ( x );否则,则x为根。

两种操作,每次给出o p , u , v

如果o p = = 1的话,让u以及所有祖先节点的权值都+ v

如果o p = = 2的话,询问[ u , v ]的权值的和

思路:

F(x)=x+lowbit(x)

这样每次最多修改l o g n个节点,相当于单点修改区间查询,用树状数组维护一下。时间复杂度是m l o g 2 n修改的函数就会这样写:

for(ll i=u;i<=n;i+=lowbit(i))
  update(i,v);//树状数组的单点修改函数

根据树状数组的性质,可以简化为下面这样:

ll num=1;
while(pos<=n){
  tr[pos]+=val*num;
  num++,pos+=lowbit(pos);
}

这样就会将修改的复杂度降到l o g n

常理说用u n o r d e r e d _ m a p就可以卡过去了,但是一直在t,只能换了手写的哈希表


存哈希表板子

const int H=8300597;
struct hash_map {
  int la[H],top;
  struct E { LL key,da; int ne; } e[int(3e6+5)];
  void clear(){
    memset(la,0,sizeof(la)); top=0;
  }
  bool count(LL k){
    static int i; i=la[k%H];
    while (i&&e[i].key!=k) i=e[i].ne;
    return i;
  }
  LL& operator[] (LL k){
    static int h,i; i=la[h=k%H];
    while (i&&e[i].key!=k) i=e[i].ne;
    if (!i) { e[i=++top]=(E){k,0,la[h]}; la[h]=top; }
    return e[i].da;
  }
} a;

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;typedef unsigned long long ull;
typedef pair<ll,ll>PLL;typedef pair<int,int>PII;typedef pair<double,double>PDD;
#define I_int ll
#define tpyeinput long long
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)
ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
//const int maxn = 1e5 + 10;
const int maxn=2e6+10,mod=8300597;
struct Hash
{
    ll e,next;
    ll w;
}edge[maxn];
ll head[mod],cnt=0;
void Init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
}
void Insert(ll x,ll val)
{
    ll temp=x%mod;
    for(ll i=head[temp];~i;i=edge[i].next)
    {
        if(edge[i].e==x)
        {
            edge[i].w+=val;
            return ;
        }
    }
    edge[cnt]=Hash{x,head[temp],val};
    head[temp]=cnt++;
}
ll Find(ll x)
{
    ll temp=x%mod;
    for(int i=head[temp];~i;i=edge[i].next)
    {
        if(edge[i].e==x) return edge[i].w;
    }
    return 0ll;
}
ll n,m;
ll lowbit(ll x){return x&-x;}
ll qask(ll pos){
  ll ans=0;
  while(pos){
    ans=ans+Find(pos);
    pos-=lowbit(pos);
  }
  return ans;
}
int main() {
  Init();
  read(n);read(m);
  while(m--){
    ll op,u,v;
    read(op);read(u);read(v);
    if(op==1){
      ll pos=u,val=v;
      ll num=1;
      while(pos<=n){
        Insert(pos,val*num);
        //table.adde(pos,val*num);
        num++,pos+=lowbit(pos);
      }
    }
    else{
      ll ans=qask(v)-qask(u-1);
      printf("%lld\n",ans);
    }
  }
  return 0;
}
/*
*/



目录
相关文章
|
6月前
|
Java
力扣经典150题第五十八题:合并两个有序链表
力扣经典150题第五十八题:合并两个有序链表
50 2
|
7月前
|
存储 算法 数据可视化
【漫画算法】哈希表:古代皇帝的秘密魔法书
【漫画算法】哈希表:古代皇帝的秘密魔法书
|
8月前
|
算法
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
63 1
|
算法
【迎战蓝桥】 算法·每日一题(详解+多解)-- day3
💖1. 链表中倒数第k个结点 💖2. 反转链表(五种解题思路) 💖3. 合并两个排序的链表
105 0
|
算法
【迎战蓝桥】 算法·每日一题(详解+多解)-- day1
【迎战蓝桥】 算法·每日一题(详解+多解)-- day1
111 0
【迎战蓝桥】 算法·每日一题(详解+多解)-- day1
|
机器学习/深度学习 存储 算法
【算法思维训练-剑指Offer联名 一】数组篇
【算法思维训练-剑指Offer联名 一】数组篇
89 0
|
算法
【迎战蓝桥】 算法·每日一题(详解+多解)-- day11
💖1. 按之字形顺序打印二叉树 💖2. 二叉搜索树的第k个节点 💖3. 二叉搜索树的第k大节点
|
存储 算法 索引
代码随想录算法训练营第六天 | 哈希表 四道简单题
代码随想录算法训练营第六天 | 哈希表 四道简单题
103 0
|
C语言
[蓝桥杯][历届试题]九宫重排(BFS+哈希)
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
203 1
[蓝桥杯][历届试题]九宫重排(BFS+哈希)
|
机器学习/深度学习 算法
【从零到蓝桥杯省一】算法详解之深度优先搜索
大家好,我是泡泡,一名算法爱好者,在学习算法的这条路上有很多的坎坷与‘大山’,想必各位都深有体会,我认为学习算法的几个很卡的点,首当其冲就是深度优先搜索和广度优先搜索,虽然理解了是什么意思但是完全敲不出来代码,练基础的题也不会写,导致了自己很迷惑,之前学的排序一类的并没有这种情况,为什么呢?实际上是因为你没有在了解算法的同时记住这个模板,y总有句话讲的很好,你并不是在构造算法,你是在学习使用模板,是啊,这是人类历史上几十年甚至上百年各个科学家智慧的结晶,对于初学肯定很难,所以就有了今天这篇文章。
141 0
【从零到蓝桥杯省一】算法详解之深度优先搜索

热门文章

最新文章