hdu4267 线段树
开始敲了一发线段树,觉得可以暴力一点的过,tle了。后来进行修改,发现了问题。
后来一看大神的做法,由于1<=k<=10,所以对于不同的k,有55个余,找答案的时候只要找不同的k值满足条件的值。
成段更新时,更新全部的树即可。
#include<stdio.h> #include<string.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn = 50010; int sum[55][maxn<<2],mark[maxn<<2],set[11],F[maxn]; void build(int l,int r,int rt) { for(int i=0;i<55;i++) sum[i][rt]=0; mark[rt]=0; if(l==r) { return; } int m=(l+r)/2; build(lson); build(rson); } void pushdown(int l,int r,int rt) { if(mark[rt]) { mark[rt<<1]=mark[rt<<1|1]=mark[rt]; for(int i=0;i<55;i++) { sum[i][rt<<1]+=sum[i][rt]; sum[i][rt<<1|1]+=sum[i][rt]; sum[i][rt]=0; } mark[rt]=0; } } void updata(int a,int b,int k,int c,int l,int r,int rt) { if(l>=a&&b>=r) { int t=set[k-1]+a%k;//由于(i-a)%k==0-->i%k==a%k mark[rt]=1; sum[t][rt]+=c; return ; } int m=(l+r)/2; if(m>=a) updata(a,b,k,c,lson); if(m<b) updata(a,b,k,c,rson); } int query(int p,int l,int r,int rt) { if(l==r) { int ans=0; for(int i=1;i<=10;i++) ans+=sum[p%i+set[i-1]][rt]; return ans; } pushdown(l,r,rt); int m=(l+r)/2; if(m>=p) return query(p,lson); else return query(p,rson); } int main() { int i,n; set[0]=0; for(i=1;i<=10;i++) set[i]=i+set[i-1]; while(~scanf("%d",&n)) { build(1,n,1); for(i=1;i<=n;i++) scanf("%d",&F[i]); int t; scanf("%d",&t); while(t--) { int m; scanf("%d",&m); if(m==1) { int a,b,k,c; scanf("%d%d%d%d",&a,&b,&k,&c); updata(a,b,k,c,1,n,1); } else { int p; scanf("%d",&p); printf("%d\n",query(p,1,n,1)+F[p]); } } } }