单点加减和区间求和
#include<stdio.h>
#include<string.h>
#define maxn 50005
int sum[maxn<<2];
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&sum[rt]);
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int p,int add,int l,int r,int rt) //单点加减
{
if(l==r)
{
sum[rt]+=add;
return;
}
int m=(l+r)>>1;
if(p<=m)
update(p,add,l,m,rt<<1);
else
update(p,add,m+1,r,rt<<1|1);
pushup(rt);
}
int query(int z,int y,int l,int r,int rt) //区间求和
{
if(z<=l&&y>=r)
{
return sum[rt];
}
int v=0;
int m=(l+r)>>1;
if(z<=m)
v+=query(z,y,l,m,rt<<1);
if(y>m)
v+=query(z,y,m+1,r,rt<<1|1);
return v;
}
int main()
{
int t,n,i,j;
scanf("%d",&t);
for(j=1;j<=t;j++)
{
printf("Case %d:\n",j);
scanf("%d",&n);
build(1,n,1);
char op[10];
while(scanf("%s",op))
{
if(op[0]=='E')
break;
int a,b;
scanf("%d %d",&a,&b);
if(op[0]=='Q')
printf("%d\n",query(a , b , 1 , n , 1));
else if (op[0] == 'S')
update(a , -b , 1 , n , 1);
else
update(a , b , 1 , n , 1);
}
}
return 0;
}
hdu 1754 I hate it
单点替换,区间最值
#include<stdio.h>
#include<string.h>
#define maxn 220005
int sum[maxn<<2];
int max(int a,int b)
{
return a>b?a:b;
}
void pushup(int rt)
{
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%d",&sum[rt]);
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
sum[rt]=-1;
pushup(rt);
}
void update(int p,int add,int l,int r,int rt)
{
if(l==r)
{
sum[rt]=add;
return;
}
int m=(l+r)>>1;
if(p<=m)
update(p,add,l,m,rt<<1);
else
update(p,add,m+1,r,rt<<1|1);
pushup(rt);
}
int query(int z,int y,int l,int r,int rt)
{
if(z<=l&&y>=r)
{
return sum[rt];
}
int v=-1;
int m=(l+r)>>1;
if(z<=m)
v=max(v,query(z,y,l,m,rt<<1));
if(y>m)
v=max(v,query(z,y,m+1,r,rt<<1|1));
return v;
}
int main()
{
int t,n,i,j,m;
while (~scanf("%d%d",&n,&m))
{
build(1,n,1);
char op[2];
while(m--)
{
int a,b;
//scanf("%c",&op);
//scanf("%d %d",&a,&b);
scanf("%s%d%d",op,&a,&b);
if(op[0]=='Q')
printf("%d\n",query(a , b , 1 , n , 1));
else
update(a , b , 1 , n , 1);
}
}
return 0;
}
hdu 1394 Minimum Inversion Number
线段树求出最初逆序数,再按性质一次算出每次的结果
单点增减,区间求和,已经算过的数值赋成1,每次查询(x[i],n-1)区间的值
#include<stdio.h>
#include<string.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 5005
int sum[maxn<<2],n;
int min(int a,int b)
{
return a<b?a:b;
}
void pushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build()
{
int i;
for(i=0;i<=n*4;i++)
sum[i]=0;
//memset(sum,0,sizeof(sum));
}
void update(int p,int l,int r,int rt)
{
if(l==r)
{
sum[rt]++;
return;
}
int m=(l+r)>>1;
if(p<=m)
update(p,lson);
else
update(p,rson);
pushUp(rt);
}
int query(int z,int y,int l,int r,int rt)
{
if(z<=l&&r<=y)
{
return sum[rt];
}
int m=(l+r)>>1;
int v=0;
if(z<=m)
v+=query(z,y,lson);
if(y>m)
v+=query(z,y,rson);
return v;
}
int main()
{
int i,num[maxn],ni,h;
while(~scanf("%d",&n))
{
ni=0;
build();
for(i=0;i<n;i++)
{
scanf("%d",&num[i]);
ni+=query(num[i],n-1,0,n-1,1);
update(num[i],0,n-1,1);
}
h=ni;
for(i=0;i<n;i++)
{
//ni+=-(num[i])+(n-num[i]-1);
ni+=n-num[i]-num[i]-1;
h=min(h,ni);
}
printf("%d\n",h);
}
return 0;
}
hdu 2759Billboard
高h宽w的广告牌,向上面贴高均为1广告(宽度不定),求能贴上的最高行
#include<stdio.h>
#include<string.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200010
int d(int a,int b)
{
return a>b?a:b;
}
int max[maxn<<2];
int h,w,n;
void build(int l,int r,int rt)
{
max[rt]=w;
if(l==r)
return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void pushUp(int rt)
{
max[rt]=d(max[rt<<1],max[rt<<1|1]);
}
int query(int x,int l,int r,int rt)
{
if(l==r)
{
max[rt]-=x;
return l;
}
int m=(l+r)>>1;
int v=(max[rt<<1]>=x)?query(x,lson):query(x,rson);
pushUp(rt);
return v;
}
int main()
{
int i,j,k,l,m;
while(~scanf("%d %d %d",&h,&w,&n))
{
int t;
if(h>n)
h=n;
build(1,h,1);
for(i=0;i<n;i++)
{
scanf("%d",&t);
if(max[1]<t)
printf("%d\n",-1);
else
printf("%d\n",query(t,1,h,1));
}
}
return 0;
}