ACM苦逼之路 线段树 树状数组

ACM训练周

时间:201 8 5 9




一. 天做了什么
1. 学习树状数组
2. 巩固线段树


二. 今天的收获及遇到的问题:
1. 小知识点,说出来都丢人,啥都不会
~scanf("%d",&n)--->scanf("%d",&n)!=EOF
int lowbit(int x)
{
return x&(-x);
}
-x是x的补码,补码为取反+1
返回值为0,x=0,
返回值为1,表示x为奇数
返回值为其他数,表示x为x与2^64的最大公约数
条件语句 中可以判断 该数是否为0,为1,能倍2整除?
利用状态位也可以 判断x是否为0
2. 问题倒没啥,就是上次线段树自己看的不牢固,今天写花了不少时间复习。

三.模板:
1. 线段树模板
分别是建树,点修改,区间求和
根据线段树从零开始自己敲的。。。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define maxn 100007
int sum[maxn<<2];
int a[maxn],n;
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=a[l];
return;
}
int m=(1+r)>>1;
build(1,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int C,int l,int r,int rt)
{
if(l==r)
{
sum[rt]+=C;
return;
}
int m=(l+r)>>1;
if(L<=m)update(L,C,l,m,rt<<1);
else update(L,C,m+1,r,rt<<1|1);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=1&&r<=R)
{
return sum[rt];
}
int m=(1+r)>>1;
int ans=0;
if(L<=m)
ans+=query(L,R,l,m,rt<<1);
if(R>=m)
ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}


2.树状数组部分模板
int lowbit(int x)
{
return x&(-x);
}
void add(int i)
{
while(i<=32002)
{
++a[i];
i+=lowbit(i);
}
}
int sum(int i)
{
int sum=0;
while(i>0)
{
sum+=a[i];
i-=lowbit(i);
}
return sum;
}

. 代码
emmmmm。。。搞一下午,跟着度娘才混出来两题。。
1.star
#include <cstdio>
#include <cstring>
int a[32002],star[15002];
int lowbit(int x)
{
return x&(-x);
}
void add(int i)
{
while(i<=32002)
{
++a[i];
i+=lowbit(i);
}
}
int sum(int i)
{
int sum=0;
while(i>0)
{
sum+=a[i];
i-=lowbit(i);
}
return sum;
}
int main()
{
int n,i,x,y;
while(scanf("%d",&n)!=EOF)
{
memset(star,0,sizeof(star));
memset(a,0,sizeof(a));
for(i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
star[sum(x+1)]++;
add(x+1);
}
for(i=0;i<n;i++)
printf("%d\n",star[i]);
}
return 0;
}


3.i hate it
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
int a[800002];
int max(int a,int b)
{
return a>b?a:b;
}
void pushup(int i)
{
a[i]=max(a[i<<1],a[i<<1|1]);
}
void build(int i,int left,int right)
{
if(left==right)
{
scanf("%d",&a[i]);
return;
}
int m=(left+right)>>1;
build(i<<1,left,m);
build(i<<1|1,m+1,right);
pushup(i);
}
void updata(int i,int left,int right,int p,int mx)
{
if(left==right)
{
a[i]=mx;
return;
}
int m=(left+right)>>1;
if(p<=m)
updata(i<<1,left,m,p,mx);
else
updata(i<<1|1,m+1,right,p,mx);
pushup(i);
}
int query(int i,int left,int right,int L,int R)
{
if(L<=left&&R>=right)
return a[i];
int m=(right+left)>>1;
int ret=0;
if(L<=m)
ret=max(ret,query(i<<1,left,m,L,R));
if(R>m)
ret=max(ret,query(i<<1|1,m+1,right,L,R));
return ret;
}

int main()
{
int m,n,i;
int aa,bb;
char s[2];
memset(a,0,sizeof(a));
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,1,n);
for(i=m;i>0;i--)
{
scanf("%s%d%d",&s,&aa,&bb);
if(s[0]=='Q')
{
printf("%d\n",query(1,1,n,aa,bb));
}
if(s[0]=='U')
{
updata(1,1,n,aa,bb);
}
}
}
return 0;
}

跟大佬后面划水,自己还差得远啊。。。嘤嘤嘤,加油!
周六陪女朋友啦。。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值