hdu 1166 敌兵布阵
单点加减和区间求和
#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; }