单点更新,区间求和,最裸的线段树
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 50010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Tree{
int l,r,num;
}tree[maxn<<2];
void pushup(int rt){
tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){
scanf("%d",&tree[rt].num);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int val,int rt){
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==r){
tree[rt].num+=val;
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(pos,val,rt<<1);
else update(pos,val,rt<<1|1);
pushup(rt);
}
int query(int x,int y,int rt){
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(x==l && y==r){
return tree[rt].num;
}
int m=(l+r)>>1;
int ans=0;
if(y<=m) ans+=query(x,y,rt<<1);
else if(m<x) ans+=query(x,y,rt<<1|1);
else {
ans+=query(x,m,rt<<1);
ans+=query(m+1,y,rt<<1|1);
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
printf("Case %d:\n",cas);
int n;
scanf("%d",&n);
build(1,n,1);
char op[10];
int x,y;
while(~scanf("%s",op)){
if(op[0]=='E') break;
scanf("%d%d",&x,&y);
if(op[0]=='A') update(x,y,1);
else if(op[0]=='S') update(x,-y,1);
else printf("%d\n",query(x,y,1));
}
}
return 0;
}
2. hdu 1754 I Hate It
单点更新,区间求最值,裸线段树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 200010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 1<<31
struct Tree{
int l,r,num;
}tree[maxn<<2];
void pushup(int rt){
tree[rt].num=max(tree[rt<<1].num,tree[rt<<1|1].num);
}
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){
scanf("%d",&tree[rt].num);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int var,int rt){
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==r){
tree[rt].num=var;
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(pos,var,rt<<1);
else update(pos,var,rt<<1|1);
pushup(rt);
}
int query(int x,int y,int rt){
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==x && y==r){
return tree[rt].num;
}
int m=(l+r)>>1;
int ans=-inf;
if(x<=m) ans=max(ans,query(x,min(m,y),rt<<1));
if(m<y) ans=max(ans,query(max(m+1,x),y,rt<<1|1));
return ans;
}
int main(){
int m,n;
while(scanf("%d%d",&n,&m)!=EOF){
build(1,n,1);
char op[10];
int x,y;
while(m--){
scanf("%s%d%d",op,&x,&y);
if(op[0]=='Q') printf("%d\n",query(x,y,1));
else update(x,y,1);
}
}
return 0;
}
3. hdu 1394 Minimum Inversion Number
求滚动之后,逆序对最少的对数,建一个节点值为0的线段树,每次插进去一个数之后,更新比他大的节点全部加1
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 5050
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Tree{
int l,r,num;
}tree[maxn];
int num[maxn];
void pushup(int rt){
tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
tree[rt].num=0;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int pos,int rt){
int l=tree[rt].l;
int r=tree[rt].r;
tree[rt].num++;
if(l==r) return ;
int m=(l+r)>>1;
if(pos<=m) update(pos,rt<<1);
else update(pos,rt<<1|1);
}
int query(int x,int y,int rt){
int l=tree[rt].l;
int r=tree[rt].r;
if(x==l && y==r){
return tree[rt].num;
}
int ans=0;
int m=(l+r)>>1;
if(y<=m) ans+=query(x,y,rt<<1);
else if(m<x) ans+=query(x,y,rt<<1|1);
else {
ans+=query(x,m,rt<<1);
ans+=query(m+1,y,rt<<1|1);
}
return ans;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
build(1,n,1);
int ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
ans+=query(num[i]+1,n,1);
update(num[i]+1,1);
}
int mx=ans;
for(int i=1;i<=n;i++){
ans=ans-num[i]+n-1-num[i];
mx=min(mx,ans);
}
printf("%d\n",mx);
}
return 0;
}
广告牌,每层至多放总宽为w的广告,每次放的时候优先考虑最上面最左边的位置,问每次放的位置的排数,不能放输出-1
线段树初始值维护一个最大值,对于当前节点,能放就放然后节点值减小val,并更新到父亲节点。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200010
struct Tree{
int l,r,num;
}tree[maxn<<2];
int h,w,n;
void pushup(int rt){
tree[rt].num=max(tree[rt<<1].num,tree[rt<<1|1].num);
}
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){
tree[rt].num=w;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
int query(int val,int rt){
int l=tree[rt].l;
int r=tree[rt].r;
if(l==r){
if(tree[rt].num<val)
return -1;
else{
tree[rt].num-=val;
return l;
}
}
int ret;
if(tree[rt<<1].num>=val)
ret=query(val,rt<<1);
else
ret=query(val,rt<<1|1);
pushup(rt);
return ret;
}
int main(){
while(scanf("%d%d%d",&h,&w,&n)!=EOF){
h=min(h,n);
build(1,h,1);
int val;
for(int i=1;i<=n;i++){
scanf("%d",&val);
printf("%d\n",query(val,1));
}
}
return 0;
}
5. CF 197div2 D. Xenia and Bit Operations
题意:求一排数字的位运算的结果,建好树之后从下往上,异或和或交替运算。
思路:距离叶子节点距离为奇数的节点操作为异或更新,距离为偶数的为或操作更新。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn (1<<17)
struct Tree{
int l,r,num,deep;
}tree[(maxn<<2)+1];
void pushup(int rt){
tree[rt].deep=tree[rt<<1].deep+1;
if(tree[rt].deep&1)
tree[rt].num=tree[rt<<1].num^tree[rt<<1|1].num;
else
tree[rt].num=tree[rt<<1].num|tree[rt<<1|1].num;
}
void build(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){
tree[rt].deep=1;
scanf("%d",&tree[rt].num);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int val,int rt){
int l=tree[rt].l;
int r=tree[rt].r;
if(l==r){
tree[rt].num=val;
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(pos,val,rt<<1);
else update(pos,val,rt<<1|1);
pushup(rt);
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
build(1,(1<<n),1);
int x,y;
while(m--){
scanf("%d%d",&x,&y);
update(x,y,1);
printf("%d\n",tree[1].num);
}
}
return 0;
}