记录编号 366208 评测结果 AAAAAAAAAA
题目名称 [HAOI 2012]高速公路 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 5.365 s
提交时间 2017-01-23 11:04:32 内存使用 26.01 MiB
显示代码纯文本
#include<cstdio>
typedef long long ll;
const int N=5e5+10;
int n,m,son[N][2],tag[N],v[N],fa[N],Root;
ll S[N],S1[N],S2[N],SV[N],s[N];
#define lc son[x][0]
#define rc son[x][1]
inline void update(int x){//暴力(求导)出奇迹 
	s[x]=s[lc]+s[rc]+1;
	SV[x]=SV[lc]+v[x]+SV[rc];
	S1[x]=S1[lc]+(s[lc]+1)*(v[x]+SV[rc])+S1[rc];
	S2[x]=S2[lc]+(s[rc]+1)*SV[lc]+v[x]*s[rc]+S2[rc];
	S[x]=S[lc]+(s[rc]+1)*S1[lc]+(s[lc]+1)*s[rc]*v[x]+S[rc]+S2[rc]*(s[lc]+1);
}
inline void update(int x,ll Tag){
	v[x]+=Tag;
	tag[x]+=Tag;
	SV[x]+=Tag*s[x];
	S1[x]+=Tag*(s[x]+1)*s[x]/2;
	S2[x]+=Tag*(s[x]-1)*s[x]/2;
	S[x]+=Tag*s[x]*(s[x]*s[x]-1)/6;
}
inline void pushdown(int x){
	if (x&&tag[x]){
		update(lc,tag[x]);
		update(rc,tag[x]);
		tag[x]=tag[0]=0;
	}
}
inline void rot(int x){
	int y=fa[x],z=fa[y];
	bool b=(x==son[y][1]);
	fa[son[y][b]=son[x][!b]]=y;
	fa[son[x][!b]=y]=x;
	fa[x]=z;
	if (y==son[z][0]) son[z][0]=x;else
	if (y==son[z][1]) son[z][1]=x;
	update(y);
	update(x);
}
inline void splay(int x){
	pushdown(x);
	while (fa[x]){
		int y=fa[x],z=fa[y];
		pushdown(z);pushdown(y);pushdown(x);
		if (!fa[y]||!fa[z]){rot(x);continue;}
		if (x==son[y][0]) rot(y==son[z][0]?y:x);
			else rot(y==son[z][1]?y:x);
		rot(x);
	}
	Root=x;
}
inline void find(int key){
	int x=Root;
	while (1){
		int i=s[lc]+1;
		if (key==i) break;
		if (key>i) x=rc,key-=i;
			else x=lc;
	}
	splay(x);
}
char ch[5];int l,r,d;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int read(){
	int x=0;bool sign=1;char ch=getchar();
	while ((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
	if (ch=='-') sign=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return sign?x:-x;
}
int main()
{
	freopen("roadxw.in","r",stdin);
	freopen("roadxw.out","w",stdout);
	scanf("%d%d",&n,&m);
	//初始化splay 
	Root=1;
	for (int i=1;i<n+2;i++) fa[son[i][1]=i+1]=i;
	for (int i=1;i<=n+2;i++) s[i]=n+3-i;
	//求解 
	while (m--){
		scanf("%s",ch);l=read();r=read();
		if (ch[0]=='C') r--;
		find(l);find(r+2);
		int le=son[Root][0],th=son[le][1];
		if (ch[0]=='C'){
			update(th,read());
			update(le);
			update(Root);
		}
		else{
			ll s=r-l+1,fz=S[th],fm=s*(s-1)/2,d=gcd(fm,fz);
			fz/=d;fm/=d;
			printf("%lld/%lld\n",fz,fm);
		}
	}
	return 0;
}