洛谷P1494 [国家集训队]小Z的袜子

 

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
# define REP(i,a,n) for(int i=a;i<=n;++i) 
# define CLR(d,a)memset(d,a,sizeof(d));

using namespace std;

void SetIO(string a){
	string in=a+".in";
	freopen(in.c_str(),"r",stdin);
}

const int maxn=60000+5;

int n,m,col[maxn];

struct Asks{
	int l,r;
	Asks(int l=0,int r=0):l(l),r(r){}
}asks[maxn];

void Read(){
	scanf("%d%d",&n,&m);

	REP(i,1,n)
		scanf("%d",&col[i]);

	REP(i,1,m){
		int a,b;
		scanf("%d%d",&a,&b);
		asks[i]=Asks(a,b);
	}
}

int block;

int belong[maxn], ranking[maxn];

int get_belong(int i){
	return (i-1)/block+1;
}

bool cmp(int i,int j){
	if(belong[asks[i].l]==belong[asks[j].l]) 
		return asks[i].r<asks[j].r;
	else 
		return belong[asks[i].l]<belong[asks[j].l];
}

void Build(){
	block=sqrt(n);

	REP(i,1,n)
		belong[i]=get_belong(i);

	REP(i,1,m)
		ranking[i]=i;

	sort(ranking+1,ranking+1+m, cmp);
}

long long square[maxn], ans[maxn];

long long cnt[maxn];

long long sum_square=0;

void update(int t, int delta){
	sum_square-=square[t];
	cnt[t]+=delta;
	square[t]=cnt[t]*cnt[t];
	sum_square+=square[t];
}

void Work(){

	int l=asks[ranking[1]].l, r=asks[ranking[1]].r;
	
	REP(i,l,r)
	    ++cnt[col[i]];

	REP(i,1,n){
		square[i]=cnt[i]*cnt[i];
		sum_square+=square[i];
	}


	REP(i,1,m){

		ans[ranking[i]]=sum_square;

		if(i==m)break;

		int l2=asks[ranking[i+1]].l;
		int r2=asks[ranking[i+1]].r;

		if(r<r2)
			REP(i,r+1,r2) update(col[i],1);
		else 
			for(int i=r;i>r2;--i) update(col[i],-1);

		if(l>l2) 
			for(int i=l-1;i>=l2;--i)update(col[i],1);
		else
			REP(i,l,l2-1)update(col[i],-1);

		l = l2;
		r = r2;
	}
}

long long gcd(long long a,long long b){
	return b==0?a:gcd(b,a%b);
}

long long up[maxn], down[maxn];

void Print(){
	REP(i,1,m){
		int l=asks[i].l;
		int r=asks[i].r;

		if(l==r){
			up[i]=0;
			down[i]=1;
		}

		else{
			int length=r-l+1;
			up[i]=ans[i]-length;
			down[i]=(long long)length*(length-1);

			if(up[i]==0){
				up[i]=0;
				down[i]=1;
				continue;
			}

			long long k=gcd(up[i],down[i]);
			up[i]/=k;
			down[i]/=k;
		} 
	}

	REP(i,1,m)
		printf("%lld/%lld\n",up[i],down[i]);
}

int main(){
	SetIO("input");
	Read();
	Build();
	Work();
	Print();
	return 0;
}

  

posted @ 2018-10-21 22:37  EM-LGH  阅读(172)  评论(0编辑  收藏  举报