总目录详见https://blog.csdn.net/mrcrack/article/details/84471041
做题原则,找不到测评地址的题不做。2018-11-28
重走长征路---OI每周刷题记录---4月26日 2014
本周共计19题+题
测评地址:
二进制:
1.「cf424C」Magic Formulas
线段树:
2.「poweroj1689」Mayor’s posters
主席树:
3.「bzoj3524」[Poi2014]Couriers 「poj2104」K-th Number
模拟:
4.「cf413A」Data Recovery
5.「cf413B」Spyke Chatting
6.「cf420A」Start Up
7.「cf420B」Online Meeting
8.「cf421A」Pasha and Hamsters
9.「bzoj1033」[ZJOI2008]杀蚂蚁antbuster
10.「bzoj1972」[Sdoi2010]猪国杀
贪心:
11.「cf413C」Jeopardy! 任务调度
线段树套平衡树:
12.「bzoj3196」JoyOI 1730 二逼平衡树
伸展树:
13.「bzoj3223」JoyOI 1729 文艺平衡树
博弈论:
14.「bzoj1874」[BeiJing2009 WinterCamp]取石子游戏
乘法逆元:
15.NOIP2011多项式系数
线段树:
16.「cf413E」Maze 2D
状压dp:
17.「cf417D」Cunning Gena
莫队算法:
18.「bzoj2038」[2009国家集训队]小Z的袜子(hose) //在线测评地址https://www.luogu.org/problemnew/show/P1494
分块+二分:
19.「bzoj3304」教主的魔法
题解:
二进制:
1.「cf424C」Magic Formulas
线段树:
2.「poweroj1689」Mayor’s posters
主席树:
3.「bzoj3524」[Poi2014]Couriers 「poj2104」K-th Number
模拟:
4.「cf413A」Data Recovery
5.「cf413B」Spyke Chatting
6.「cf420A」Start Up
7.「cf420B」Online Meeting
8.「cf421A」Pasha and Hamsters
9.「bzoj1033」[ZJOI2008]杀蚂蚁antbuster
10.「bzoj1972」[Sdoi2010]猪国杀
贪心:
11.「cf413C」Jeopardy! 任务调度
线段树套平衡树:
12.「bzoj3196」JoyOI 1730 二逼平衡树
伸展树:
13.「bzoj3223」JoyOI 1729 文艺平衡树
博弈论:
14.「bzoj1874」[BeiJing2009 WinterCamp]取石子游戏
乘法逆元:
15.NOIP2011多项式系数
线段树:
16.「cf413E」Maze 2D
状压dp:
17.「cf417D」Cunning Gena
莫队算法:
18.「bzoj2038」[2009国家集训队]小Z的袜子(hose)
//P1494 [国家集训队]小Z的袜子
//在线测评地址https://www.luogu.org/problemnew/show/P1494
//为了防止骗分,采取一个例子中多次询问。
//扫了样例,发现0/1,1/1挺好处理。
//N=50000 C(50000,2)=50000*49999/2=2499950000/2=1249975000,2^31-1=2147483648,当心,操控不好,int要溢出
// 2/5 这样算 (C(2,2)+C(3,2))/C(5,2)=(1+3)/10=2/5
// 4/15 这样算 (C(2,2)+C(3,2))/C(6,2)=(1+3)/15=4/15
//样例会算后,初步的算法也就有了
//需要统计 在 某一区间内 各个颜色的数目,这是最关键的。
//想法中,前缀和,线段树,冒了出来
//前缀和,N=5000,M=5000,每次查询,统计每种颜色数量,需算5000,共5000次查询,需算5000*5000=2.5*10^7,前缀和,30分到头。
//用线段树,只求过,一个区间 的和,最大值,最小值。一个区间要 同时存储多个量还真没处理过。
//仔细想想,可以每种颜色开一个线段数,N=50000开50000棵线段树,每棵数占空间4*50000=200000,需开50000*200000=10^10,必爆空间
//N=25000,开25000棵线段树,每棵树占空间25000*4=10^5,总空间25000*10^5=2.5*10^9必爆空间
//以目前知识结构,拿30分比较稳妥。采用前缀和。
//5000*5000*4/1024/1024=95.4MB 不可能开最大了,该题该法,目标30分
//编写完一部分功能,马上测试,这是基本要求。
//样例很快通过,提交0分,测试点1-7,10RE,测试点8-9TLE。2019-2-13 12:28
//翻看题目,发现,有这么一句,然而数据中有L=R的情况,请特判这种情况,输出0/1。
//确实,问题出在读题上。
//修改,提交30分,测试点4-7,9-10RE,测试点7-8TLE。
//目的达成,以下为30分代码。2019-2-13 12:36
//想了想,之前测试点1-3RE的原因是,分母为0.
//学习莫队算法,此文介绍得不错https://www.cnblogs.com/Paul-Guderian/p/6933799.html
//但不是很喜欢上文的代码风格。
//开始莫队算法编写
//因用到sort函数,开始C++
//样例通过,提交AC。2019-2-13 19:54
//该题多处,int溢出。故采用 long long
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL long long
#define maxn 50100
int sum[maxn],color[maxn],n,m,block[maxn];//color[x]存储x位置的颜色
LL ans=0;
struct node{
int left,right,id;
LL a,b;
}q[maxn];//m个查询
LL gcd(LL a,LL b){//最大公约数
return b?gcd(b,a%b):a;
}
int cmp(struct node a,struct node b){
return block[a.left]==block[b.left]?a.right<b.right:a.left<b.left;
}
int cmp2(struct node a,struct node b){
return a.id<b.id;
}
LL square(LL x){
return x*x;
}
void modify(int x,int delta){
ans-=square(sum[color[x]]),sum[color[x]]+=delta,ans+=square(sum[color[x]]);
}
int main(){
int i,left,right,unit;
LL a,b,t,d;
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&m),unit=(int)(sqrt(n)+0.5);
for(i=1;i<=n;i++)scanf("%d",&color[i]),block[i]=i/unit;
for(i=1;i<=m;i++)scanf("%d%d",&q[i].left,&q[i].right),q[i].id=i;
sort(q+1,q+1+m,cmp);
left=1,right=0;
for(i=1;i<=m;i++){
while(left<q[i].left)modify(left,-1),left++;
while(left>q[i].left)modify(left-1,1),left--;
while(right>q[i].right)modify(right,-1),right--;
while(right<q[i].right)modify(right+1,1),right++;
if(q[i].left==q[i].right){q[i].a=0,q[i].b=1;continue;}
t=q[i].right-q[i].left+1;
a=ans-t;//此处写成 a=ans+t; 查了会
b=t*(t-1);
d=gcd(a,b);
q[i].a=a/d,q[i].b=b/d;
}
sort(q+1,q+1+m,cmp2);
for(i=1;i<=m;i++)printf("%lld/%lld\n",q[i].a,q[i].b);
return 0;
}
//P1494 [国家集训队]小Z的袜子
//在线测评地址https://www.luogu.org/problemnew/show/P1494
//为了防止骗分,采取一个例子中多次询问。
//扫了样例,发现0/1,1/1挺好处理。
//N=50000 C(50000,2)=50000*49999/2=2499950000/2=1249975000,2^31-1=2147483648,当心,操控不好,int要溢出
// 2/5 这样算 (C(2,2)+C(3,2))/C(5,2)=(1+3)/10=2/5
// 4/15 这样算 (C(2,2)+C(3,2))/C(6,2)=(1+3)/15=4/15
//样例会算后,初步的算法也就有了
//需要统计 在 某一区间内 各个颜色的数目,这是最关键的。
//想法中,前缀和,线段树,冒了出来
//前缀和,N=5000,M=5000,每次查询,统计每种颜色数量,需算5000,共5000次查询,需算5000*5000=2.5*10^7,前缀和,30分到头。
//用线段树,只求过,一个区间 的和,最大值,最小值。一个区间要 同时存储多个量还真没处理过。
//仔细想想,可以每种颜色开一个线段数,N=50000开50000棵线段树,每棵数占空间4*50000=200000,需开50000*200000=10^10,必爆空间
//N=25000,开25000棵线段树,每棵树占空间25000*4=10^5,总空间25000*10^5=2.5*10^9必爆空间
//以目前知识结构,拿30分比较稳妥。采用前缀和。
//5000*5000*4/1024/1024=95.4MB 不可能开最大了,该题该法,目标30分
//编写完一部分功能,马上测试,这是基本要求。
//样例很快通过,提交0分,测试点1-7,10RE,测试点8-9TLE。2019-2-13 12:28
//翻看题目,发现,有这么一句,然而数据中有L=R的情况,请特判这种情况,输出0/1。
//确实,问题出在读题上。
//修改,提交30分,测试点4-7,9-10RE,测试点7-8TLE。
//目的达成,以下为30分代码。2019-2-13 12:36
//想了想,之前测试点1-3RE的原因是,分母为0.
#include <stdio.h>
#include <string.h>
#define LL long long
int sum[5010][5010],n,m;
LL gcd(LL a,LL b){//最大公约数
return b?gcd(b,a%b):a;
}
int main(){
int i,j,color,left,right;
LL a,b,t,d;
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&color);
for(j=1;j<=n;j++){
if(j==color)sum[i][j]+=sum[i-1][j]+1;
else sum[i][j]+=sum[i-1][j];
}
}
while(m--){
scanf("%d%d",&left,&right);
if(left==right){//读题问题,漏了此种情况,然而数据中有L=R的情况,请特判这种情况,输出0/1。
printf("0/1\n");
continue;
}
t=right-left+1;
a=t*(t-1)/2,b=0;
for(j=1;j<=n;j++){
t=sum[right][j]-sum[left-1][j];
if(t>=2)b+=t*(t-1)/2;
}
d=gcd(a,b);
printf("%lld/%lld\n",b/d,a/d);//此处写成 printf("%d/%d\n",b/d,a/d);
}
return 0;
}
分块+二分:
19.「bzoj3304」教主的魔法