單點更新,區間求和,最裸的線段樹
#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;
}