NOIP2013 提高组 Day1
https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%7C30
期望得分:100+100+100=300
实际得分:100+10+0=110
T2 思路有漏洞
T3 求到lca的什么什么值,指跳了一个点,没管另一个,丢100
T1 转圈游戏
题目描述
n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,第n − m号位置上的小伙伴走到第 0 号位置,第n-m+1 号位置上的小伙伴走到第 1 号位置,……,第 n-1 号位置上的小伙伴顺时针走到第m-1 号位置。
现在,一共进行了 10^k轮,请问 x 号小伙伴最后走到了第几号位置。
输入输出格式
输入格式:
输入文件名为 circle.in。
输入共 1 行,包含 4 个整数 n、m、k、x,每两个整数之间用一个空格隔开。
输出格式:
输出文件名为 circle.out。
输出共 1 行,包含 1 个整数,表示 10
k 轮后 x 号小伙伴所在的位置编号。
输入输出样例
10 3 4 5
5
说明
对于 30%的数据,0 < k < 7;
对于 80%的数据,0 < k < 10^7;
对于 100%的数据,1 <n < 1,000,000,0 < m < n,1 ≤ x ≤ n,0 < k < 10^9
每次移动m个位置,共移动10^k次,
用快速幂算出移动的总步数,加上x再%n
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,k,x;
long long tmp=;
void mul(long long a,long long b)
{
for(;b;b>>=,a=a*a%n)
if(b&) tmp=tmp*a%n;
tmp=m*tmp%n;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&x);
mul(,k);
printf("%d",(x+tmp)%n);
}
T2 火柴排队
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入输出格式
输入格式:
输入文件为 match.in。
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:
输出文件为 match.out。
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
输入输出样例
【输入输出样例 1】
4
2 3 1 4
3 2 1 4
【输入输出样例 2】
4
1 3 4 2
1 7 2 4
【输入输出样例 1】
1
【输入输出样例 2】
2
说明
【输入输出样例说明1】
最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
【输入输出样例说明2】
最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。
【数据范围】
对于 10%的数据, 1 ≤ n ≤ 10;
对于 30%的数据,1 ≤ n ≤ 100;
对于 60%的数据,1 ≤ n ≤ 1,000;
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
∑(ai-bi)^2=Σ ai² + Σ bi² - 2 Σ ai * bi
ai² ,b²是固定的
所以要最大化 ai * bi
下意识觉得 将a、b排序后对应顺序相乘的结果最大,正确
证明如下:
由排序不等式:
设有两组数 a1 , a2 ,…… an; b1 , b2 ,…… bn 满足 a1 ≤ a2 ≤……≤ an, b1 ≤ b2 ≤……≤ bn ,
其中c1,c2,……,cn是b1,b2,……,bn的任一排列,则有
a1* bn + a2 *b{n-1}+ ... + an *b1
≤ a1 *c1 + a2* c2 +……+ an *cn
≤ a1 *b1 + a2 *b2 + ……+an* bn.
即 逆序和<=乱序和<=顺序和
所以最大化ai * bi,就要顺序相乘
所以问题就转化为
在b数组中,交换最少的次数,
使得 若a[i]在a数组中排名为j,b[i]也在b数组中排名为j
设一个数组s,s[i]=j表示 b原序列中第i个元素,应该在位置j
然后问题转化为了求s[]的逆序对个数
AC代码:
#include<cstdio>
#include<algorithm>
#define N 100001
#define mod 99999997
using namespace std;
int n,ans,tmp[N],s[N];
struct node
{
int w,id;
}a[N],b[N];
bool cmp(node p,node q)
{
return p.w<q.w;
}
void solve(int l,int r)
{
if(l==r) return;
int mid=l+r>>;
solve(l,mid);
solve(mid+,r);
int i=l,j=mid+,k=l;
while(i<=mid&&j<=r)
{
if(s[i]<=s[j]) tmp[k++]=s[i++];
else
{
ans=(ans+mid-i+)%mod;
tmp[k++]=s[j++];
}
}
while(i<=mid) tmp[k++]=s[i++];
while(j<=r) tmp[k++]=s[j++];
for(int i=l;i<=r;i++) s[i]=tmp[i];
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i].w),a[i].id=i;
for(int i=;i<=n;i++) scanf("%d",&b[i].w),b[i].id=i;
sort(a+,a+n+,cmp);
sort(b+,b+n+,cmp);
for(int i=;i<=n;i++) s[b[i].id]=a[i].id;
solve(,n);
printf("%d",ans);
}
自己做的错误思路:
将a数组从大到小排序,对应的b随之排序,求b中 i>j,b[i]<b[j]的个数
错误1:
逆序对定义:i<j,a[i]>a[j],归并排序求逆序对模版是按i<j来的
错误2:
重排a数组,b数组随之排,这样归并排序完后得到b的循序序列
但改变了a数组,即改变了原序列
WA 10分代码:
#include<cstdio>
#include<algorithm>
#define N 100001
#define mod 99999997
using namespace std;
int n,ans,tmp[N],s[N];
struct node
{
int a,b;
}e[N];
bool cmp(node p,node q)
{
return p.a<q.a;
}
void solve(int l,int r)
{
if(l==r) return;
int mid=l+r>>;
solve(l,mid);
solve(mid+,r);
int i=l,j=mid+,k=l;
while(i<=mid&&j<=r)
{
if(s[i]<=s[j]) tmp[k++]=s[i++];
else
{
ans=(ans+mid-i+)%mod;
tmp[k++]=s[j++];
}
}
while(i<=mid) tmp[k++]=s[i++];
while(j<=r) tmp[k++]=s[j++];
for(int i=l;i<=r;i++) s[i]=tmp[i];
}
int main()
{
/*freopen("data","r",stdin);
freopen("my.out","w",stdout);*/
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&e[i].a);
for(int i=;i<=n;i++) scanf("%d",&e[i].b);
sort(e+,e+n+,cmp);
for(int i=;i<=n;i++) s[i]=e[i].b;
solve(,n);
printf("%d",ans);
}
T3 货车运输
题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入输出格式
输入格式:
输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。
输出格式:
输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
输入输出样例
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
3
-1
3
说明
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;
对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。
题意:若点x、y连通,求x、y路径上限重的最小值;若不连通,输出-1
注:数据有重边、有环
重边肯定保留限重最大的那一条,所选的道路限重越大越好
所以 是最大生成树
在最大生成树上倍增,同时维护倍增区域的最小值
答案就是两点到其lca路径上,所有倍增区域的最小值
#include<map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 10001
using namespace std;
int timee,n,m,p,ances[N][],id[N],minn[N][],tot,q;
int front[N],nextt[N*],to[N*],w[N*];
int bl[N],k,fa[N],cnt;
struct node
{
int u,v,c;
}e[N*];
void dfs(int x)
{
id[x]=++cnt;
bl[x]=timee;
for(int i=front[x];i;i=nextt[i])
{
if(to[i]==ances[x][]) continue;
ances[to[i]][]=x;
minn[to[i]][]=w[i];
dfs(to[i]);
}
}
void add(int u,int v,int val)
{
to[++tot]=v; nextt[tot]=front[u]; front[u]=tot; w[tot]=val;
}
void pre()
{
for(int i=;i<=n;i++)
if(!id[i])
{
timee++;
dfs(i);
}
int tmp;
q=int(log(n)/log()+);
for(int i=;i<=q;i++)
for(int j=;j<=n;j++)
{
ances[j][i]=ances[ances[j][i-]][i-];
if(!ances[j][i]) continue;
tmp=min(minn[j][i-],minn[ances[j][i-]][i-]);
minn[j][i]=tmp;
}
}
int find(int i) {return fa[i]==i ? fa[i] : fa[i]=find(fa[i]);}
void solve(int x,int y)
{
if(bl[x]!=bl[y])
{
printf("-1\n");
return;
}
int ans=;
if(id[x]<id[y]) swap(x,y);
for(int i=q;i>=;i--)
if(id[ances[x][i]]>id[y])
{
ans=min(ans,minn[x][i]);
x=ances[x][i];
}
ans=min(ans,minn[x][]);
x=ances[x][];
if(x!=y)
{
for(int i=q;i>=;i--)
if(id[ances[y][i]]>id[x])
{
ans=min(ans,minn[y][i]);
y=ances[y][i];
}
ans=min(ans,minn[y][]);
}
printf("%d\n",ans);
}
bool cmp(node a,node b)
{
return a.c>b.c;
}
void make_tree()
{
int a,b,j=,r1,r2;
int h=;
while(h<n-&&j<=m)
{
a=e[j].u;b=e[j].v;
r1=find(a);r2=find(b);
if(r1!=r2)
{
h++;
fa[r1]=r2;
add(a,b,e[j].c);add(b,a,e[j].c);
}
j++;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) fa[i]=i;
int u,v,a;
for(int i=;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
sort(e+,e+m+,cmp);
make_tree();
pre();
scanf("%d",&p);
while(p--)
{
scanf("%d%d",&u,&v);
solve(u,v);
}
}
考试时的错误:
1、跳了x没跳y
2、跳y之前没有判断y是否就是lca
NOIP2013 提高组 Day1的更多相关文章
- noip2013提高组day1第一题-转圈游戏——快速幂典型应用
所谓的快速幂: // 计算 m^n % k 的快速幂算法 int quickpow(int m,int n,int k) { ; ) { ) b = (b*m)%k; n = n >> ; ...
- JZOJ 3534. 【NOIP2013提高组day1】货车运输
Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的 ...
- luogu1003铺地毯[noip2011 提高组 Day1 T1]
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...
- [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路
[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...
- 18/9/9牛客网提高组Day1
牛客网提高组Day1 T1 中位数 这好像是主席树??听说过,不会啊... 最后只打了个暴力,可能是n2logn? 只过了前30% qwq #include<algorithm> #in ...
- Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数
Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...
- Noip2011 提高组 Day1 T3 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】
国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...
- [NOIP2013 提高组] 华容道 P1979 洛谷
[NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...
随机推荐
- Scrum立会报告+燃尽图(Beta阶段第二周第三次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2411 项目地址:https://coding.net/u/wuyy694 ...
- Beta周王者荣耀交流协会第六次会议
1.立会照片 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:袁玥 2. 时间跨度 2017年11月15日 19:00 — 19:10 ,总计10分钟. 3. 地点 一食堂 ...
- “Hello World!”团队第三周召开的第二次会议
今天是我们团队“Hello World!”团队第三周召开的第二次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时间 ...
- Python学习之路7 - 生成器&迭代器
本章内容: 列表生成式 生成器 yield 迭代器 列表生成式 当我们要定义一个列表的时候,我们通常用这种方式a = [1,2,3],但是如果我们定义了一个比较长的列表的时候,手动定义列表就会比较麻烦 ...
- 团队backlog和燃尽图
首先我们的团队的任务是做一款一对一交流的软件,我们团队的backlog如下: 用电脑搭建一个服务器一对一平台 实现数据库和Android的链接 编写登陆,注册页面,和登陆成功界面,和登陆失败页面 实现 ...
- 基础算法学习2-dp
一.算法题: 最大子阵 给定一个n×m 的矩阵 A,求A 中的一个非空子矩阵,使这个子矩阵中的元素和最大.其中,A 的子矩阵指在 A 中行和列均连续的一部分.输入格式输入的第一行包含两个整数 n,m( ...
- lintcode-422-最后一个单词的长度
422-最后一个单词的长度 给定一个字符串, 包含大小写字母.空格' ',请返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 注意事项 一个单词的界定是,由字母组成,但不包含任何的空 ...
- Struts2(七)
以下内容是基于导入struts2-2.3.32.jar包来讲的 1.xml验证 Struts2提供了验证器,实现了通用的验证逻辑.例如: 非空验证器.长度验证器.日期验证器.email验证器等.具体定 ...
- 运维堡垒机----Gateone
简介: 运维堡垒机的理念起源于跳板机.2000年左右,高端行业用户为了对运维人员的远程登录进行集中管理,会在机房里部署跳板机.跳板机就是一台服务器,维护人员在维护过程中,首先要统一登录到这台服务器上, ...
- python脚本批量生成50000条插入数据的sql语句
f = open("xx.txt",'w') for i in range(1,50001): str_i = str(i) realname = "lxs"+ ...