bzoj2752 [HAOI2012]高速公路(road)
线段树好题。
很容易求出要维护的东西的公式,给线段标号,设x,y为左右线段标号,那么其中出现的总和就是Σc[i]*((i-x)*(y-i)+(y-x)),拆开就是Σ(y-x-y*x)*c[i]+(x+y)*i*c[i]-i2*c[i].
于是只要维护∑c[i],∑i*c[i],∑i2*c[i]就行了。
我一开始想偷懒写bit发现用了bit以后维护的和会升至3维,(⊙o⊙)…三维求和,略难搞,只好放弃。
那么就是线段树,用一个求和公式就行了。
看来以后要多练练线段树了,实在是偷懒偷的太多了......
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 800000 7 #define inf 2147483647 8 using namespace std; 9 long long key[4][maxn],cov[maxn]; 10 int n,m; 11 long long ll,rr; 12 13 inline void cover(int x,long long l,long long r,long long z) 14 { 15 key[1][x]+=z*(r-l+1); 16 key[2][x]+=z*(l+r)*(r-l+1)/2; 17 key[3][x]+=z*(r*(r+1)*(2*r+1)-(l-1)*l*(2*l-1))/6; 18 } 19 20 inline void down(int x,int l,int r) 21 { 22 int mid=(l+r)>>1; 23 cov[x*2]+=cov[x]; 24 cov[x*2+1]+=cov[x]; 25 cover(x*2,l,mid,cov[x]); 26 cover(x*2+1,mid+1,r,cov[x]); 27 cov[x]=0; 28 } 29 30 inline void add(int x,int l,int r,long long z) 31 { 32 if (ll<=l&&r<=rr) 33 { 34 cov[x]+=z; 35 cover(x,l,r,z); 36 return ; 37 } 38 down(x,l,r); 39 int mid=(l+r)>>1; 40 if (ll<=mid) add(x*2,l,mid,z); 41 if (rr>mid) add(x*2+1,mid+1,r,z); 42 for (int i=1;i<=3;i++) key[i][x]=key[i][x*2]+key[i][x*2+1]; 43 } 44 45 inline long long ask(int k,int x,int l,int r) 46 { 47 long long tmp=0; 48 if (ll<=l&&r<=rr) return key[k][x]; 49 down(x,l,r); 50 int mid=(l+r)>>1; 51 if (ll<=mid) tmp+=ask(k,x*2,l,mid); 52 if (rr>mid) tmp+=ask(k,x*2+1,mid+1,r); 53 for (int i=1;i<=3;i++) key[i][x]=key[i][x*2]+key[i][x*2+1]; 54 return tmp; 55 } 56 57 inline long long gcd(long long a,long long b) 58 { 59 if (a==0) return b; 60 else return gcd(b%a,a); 61 } 62 63 int main() 64 { 65 //freopen("road4.in","r",stdin); 66 //freopen("road.out","w",stdout); 67 scanf("%d%d",&n,&m); 68 n=n-1; 69 int x,y,z; 70 char sign; 71 for (int i=1;i<=m;i++) 72 { 73 scanf("\n%c",&sign); 74 if (sign=='C') 75 { 76 scanf("%d%d%d",&x,&y,&z); 77 ll=x; rr=y-1; 78 add(1,1,n,z); 79 } 80 else 81 if (sign=='Q') 82 { 83 scanf("%d%d",&x,&y); 84 ll=x; rr=y-1; 85 long long a1=(rr-ll-rr*ll+1)*ask(1,1,1,n); 86 long long a2=(ll+rr)*ask(2,1,1,n); 87 long long a3=ask(3,1,1,n); 88 long long ans=a1+a2-a3; 89 long long sum=(rr-ll+1)*(rr-ll+2)/2; 90 long long tmp; 91 if (ans>sum) tmp=gcd(sum,ans); else tmp=gcd(ans,sum); 92 printf("%lld/%lld\n",ans/tmp,sum/tmp); 93 } 94 } 95 return 0; 96 }
AC without art, no better than WA !