这题……我从一开始就想歪了qwq。
为了缅怀逝去的一小时我就把我的30分暴力思路放上来。
首先我们观察枚举的区间。假设我们要枚举的范围是1~5之间的四条路,为了方便我们把它们叫做abcd。
那么观察我们枚举的区间。
a ab abc abcd b bc bcd c cd d
观察有一些区间是可以合起来的。
然后观察a出现4次,b出现6次,c出现6次,d出现4次。
是有一定规律的qwq
然后就$\frac{nm}{2}的复杂度搞搞 就三十分
正确思路是,观察一条路选不选上(设这条路左点x):左区间在(l,x),右区间在(x+1,r)
这些区间会把这条路选上。
于是这条路选上的次数就等于(x-l+1)(r-x)s[x]
化简得到x*s[x]、s[x]、x^2*s[x]三种可以用线段树维护的东西
然后线段树搞
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<cstdlib> #define left (rt<<1) #define right (rt<<1|1) #define mid ((l+r)>>1) #define lson l,mid,left #define rson mid+1,r,right inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch==‘-‘) f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-‘0‘; ch=getchar(); } return num*f; } long long gcd(long long a,long long b){ return b==0?a:gcd(b,a%b); } long long sum[1000010]; long long mul[1000010]; long long tree[1000010]; long long sree[1000010]; long long mree[1000010]; long long tag[1000010]; inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; sree[rt]=sree[left]+sree[right]; mree[rt]=mree[left]+mree[right]; } void pushdown(int rt,int l,int r){ if(tag[rt]==0) return; tag[left]+=tag[rt]; tag[right]+=tag[rt]; tree[left]+=tag[rt]*((r-l+1)-((r-l+1)>>1)); tree[right]+=tag[rt]*((r-l+1)>>1); sree[left]+=tag[rt]*(sum[mid]-sum[l-1]); sree[right]+=tag[rt]*(sum[r]-sum[mid]); mree[left]+=tag[rt]*(mul[mid]-mul[l-1]); mree[right]+=tag[rt]*(mul[r]-mul[mid]); tag[rt]=0; } void update(int from,int to,long long num,int l,int r,int rt){ if(from<=l&&to>=r){ tag[rt]+=num; tree[rt]+=num*(r-l+1); sree[rt]+=num*(sum[r]-sum[l-1]); mree[rt]+=num*(mul[r]-mul[l-1]); return; } pushdown(rt,l,r); if(from<=mid) update(from,to,num,lson); if(to>mid) update(from,to,num,rson); pushup(rt); } struct Ans{ long long x,y,z; void clear(){x=y=z=0;} Ans operator +(const Ans a){ Ans ans=(Ans){x+a.x,y+a.y,z+a.z}; return ans; } }; Ans query(int from,int to,int l,int r,int rt){ if(from<=l&&to>=r) return(Ans){tree[rt],sree[rt],mree[rt]}; pushdown(rt,l,r); Ans opt; opt.clear(); if(from<=mid) opt=query(from,to,lson); if(to>mid) opt=opt+query(from,to,rson); return opt; } int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i){ sum[i]=sum[i-1]+i; mul[i]=mul[i-1]+1LL*i*i; } for(int i=1;i<=m;++i){ char ch[10]; scanf("%s",ch);int x=read(),y=read(); if(ch[0]==‘C‘){ long long z=read(); update(x,y-1,z,1,n-1,1); } else{ Ans now=query(x,y-1,1,n-1,1); long long ans=0; ans+=now.y*(long long)(x+y-1); ans+=now.x*(long long)(1LL*y-1LL*x*y); ans-=now.z; long long len=y-x+1; long long cnt=len*(len-1)/2; long long gc=gcd(ans,cnt); ans/=gc; cnt/=gc; printf("%lld/%lld\n",ans,cnt); } } return 0; }
原文地址:https://www.cnblogs.com/cellular-automaton/p/8214962.html
时间: 2024-10-08 13:07:03