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;
}
/*
*/



目录
相关文章
|
8天前
|
算法 测试技术 C#
【欧拉回路】【图论】【并集查找】765. 情侣牵手
【欧拉回路】【图论】【并集查找】765. 情侣牵手
|
8天前
好题记录:
好题记录:
29 1
|
7月前
|
算法
【算法挨揍日记】day12——153. 寻找旋转排序数组中的最小值、LCR 173. 点名
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
93 1
|
9月前
|
人工智能 Go
树状数组(包教包会,不会抽我)
树状数组(包教包会,不会抽我)
46 0
|
11月前
|
机器学习/深度学习 存储 算法
【算法思维训练-剑指Offer联名 一】数组篇
【算法思维训练-剑指Offer联名 一】数组篇
66 0
|
11月前
|
C语言 C++
PTA团体程序设计天梯赛-练习集: L1-050 倒数第N个字符串 ( 15分 )
给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。 输入格式: 输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤105)。 输出格式: 在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。 输入样例:
132 0
|
存储 算法 索引
代码随想录算法训练营第六天 | 哈希表 四道简单题
代码随想录算法训练营第六天 | 哈希表 四道简单题
76 0
|
人工智能 Python
2019CCPC厦门站 A. Zayin and Bus(bfs 贪心 排序)
2019CCPC厦门站 A. Zayin and Bus(bfs 贪心 排序)
64 0
|
存储 人工智能
PTA团体程序设计天梯赛-练习集 L3-010 是否完全二叉搜索树(顺序存储)
PTA团体程序设计天梯赛-练习集 L3-010 是否完全二叉搜索树(顺序存储)
86 0
|
消息中间件 uml
gym102394 2019CCPC哈尔滨 A. Artful Paintings(二分 差分约束 优化)
gym102394 2019CCPC哈尔滨 A. Artful Paintings(二分 差分约束 优化)
144 0