2018HUAS_ACM暑假比赛5题解
Problem A
- 思路
这是一道带权并查集问题
因为只有三种种类,我们分别用0,1,2来表示,即0-->1,1-->2,2-->0。
我们需要知道x和y的关系,即需知道x和祖先xx的关系,y和祖先yy的关系,即可得x和y的关系。
①当x的祖先和y的祖先不同时,可知x和y的关系在前面并没有体现,所以此话一定是真的
②当x的祖先和y的祖先相同时,通过x,y和祖先的关系可知x所在种类和y所在种类的关系,即可判断话的真假
- AC代码
#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
ll n,k,p,x,y,ans;
ll f[50005],val[50005];
int found(ll x)
{
if(x==f[x])return x;
ll temp=found(f[x]);
val[x]=(val[x]+val[f[x]])%3;
return f[x]=temp;
}
int fun(ll d,ll x,ll y)
{
ll xx=found(x);
ll yy=found(y);
if(xx!=yy)
{
f[yy]=xx;
val[yy]=(val[x]-val[y]+d+3)%3;
return 0;
}
else
{
if((val[y]-val[x]+3)%3==d)return 0;
else return 1;
}
}
int main()
{
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)f[i]=i;
while(k--)
{
scanf("%lld%lld%lld",&p,&x,&y);
if(x>n||y>n||(p==2&&x==y)){++ans;continue;}
if(fun(p-1,x,y))++ans;
}
printf("%lld\n",ans);
return 0;
}
Problem B
- 思路
此题是一个思维题,里面有用到线段树的知识
因为是从1开始变到p,所以数组中必然要有p出现。
其中所有的0都要变为非0且小于等于q的数字,我们只需要把0变为左边相邻的数字即可,注意第一个数字为0时的情况
然后记录所有数字出现的最小和最大位置,即可得到一个区域,在此区域若出现比其小的数字,则不可能。
- AC代码
#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
int n,q,a[200005],st[1000000],g=0,b[200005][2];
void build(int root,int l,int r)
{
if(l==r)st[root]=a[l];
else
{
int mid=(l+r)>>1;
build(root<<1,l,mid);
build((root<<1)+1,mid+1,r);
st[root]=min(st[root<<1],st[(root<<1)+1]);
}
}
int query(int root,int l,int r,int s,int e)
{
if(l>e||r<s)return INF;
if(s<=l&&e>=r)return st[root];
int mid=(l+r)>>1;
return min(query(root<<1,l,mid,s,e),query((root<<1)+1,mid+1,r,s,e));
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
//判断是否有最大的数字
for(int i=1;i<=n;i++)
if(a[i]==q){g=1;break;}
//将所有的0变成非0数字,保证数组里要有最大的数字
int l=0;
if(!g)
{
for(l=l+1;l<=n;l++)
if(!a[l]){a[l]=q;break;}
if(l>n){cout<<"NO"<<endl;return 0;}
}
else if(!a[1])
{
for(l=2;l<=n;l++)
if(a[l])break;
for(int i=1;i<l;i++)
a[i]=a[l];
}
for(;l<=n;l++)if(!a[l])a[l]=a[l-1];
//记录数字出现的最小的位置和最大的位置
for(int i=1;i<=n;i++)
{
if(!b[a[i]][0])b[a[i]][0]=i;
b[a[i]][1]=i;
}
build(1,1,n);
//判断此数字出现的区间里是否有比它小的数字出现
for(int i=1;i<=q;i++)
{
if(!b[i][0])continue;
if(query(1,1,n,b[i][0],b[i][1])<i)
{
cout<<"NO"<<endl;
return 0;
}
}
cout<<"YES"<<endl;
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<endl;
return 0;
}
Problem C
- 思路
这题最难绕的就是“左子树+右子树”并不等于总的,因为它update的时候右子树是特殊计算的。还是因为在这个最长上升序列的问题中虽然计算单个区间的时候是不考虑左右影响的,但是update的时候为了正确得到这个区间的结果,右子树还是要考虑左子树的影响的,这是造成val[i<<1]+val[(i<<1)+1]≠≠val[i]的原因。
- AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,val[500010];
double Max[500010];
bool dlt[500010];
int divide(int i,int l,int r,double v){
if (l==r) return Max[i]>v;
int mid=(l+r)>>1;
if (Max[i]<=v) return 0;
if (Max[i<<1]<=v) return divide((i<<1)+1,mid+1,r,v);
else return val[i]-val[i<<1]+divide(i<<1,l,mid,v);
}
void change(int i,int l,int r,int x,double v){
if (l==r){
Max[i]=v;val[i]=1;
return;
}
int mid=(l+r)>>1;
if (x<=mid) change(i<<1,l,mid,x,v);
else change((i<<1)+1,mid+1,r,x,v);
Max[i]=max(Max[i<<1],Max[(i<<1)+1]);
val[i]=val[i<<1]+divide((i<<1)+1,mid+1,r,Max[i<<1]);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
double v=(double)y/(double)x;
change(1,1,n,x,v);
printf("%d\n",val[1]);
}
return 0;
}
Problem D
- 思路
dp+最短路
令f[i]为到第i天的最少成本,那么显然有f[i]=min(f[i],f[j]+cost(j+1,i)+k),其中cost(i,j)为i天到j天的最小花费,然后直接最短路搞
- AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
vector<pair<int,int> >e[maxn];
int d[maxn];
int vis[maxn];
int unreach[maxn][maxn];
int f[maxn];
int n,m,k,ee;
int dijkstra(int s,int t)
{
memset(vis,0,sizeof(vis));
for(int i = s;i<=t;i++)
for(int j = 1;j<=m;j++)
{
if(unreach[j][i])
vis[j]=1;
}
for(int i = 1;i<=m;i++)
d[i]=9999999;
queue<int>q;
d[1]=0;
q.push(1);
// vis[1]=1;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0;i<e[u].size();i++)
{
int v= e[u][i].first;
if(vis[v])
continue;
if(d[v]>d[u]+e[u][i].second)
{
d[v]=d[u]+e[u][i].second;
//vis[v]=1;
q.push(v);
}
}
}
return d[m]*(t-s+1);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&ee);
for(int i = 0;i<ee;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[u].push_back(make_pair(v,w));
e[v].push_back(make_pair(u,w));
}
int q;
scanf("%d",&q);
while(q--)
{
int u,a,b;
scanf("%d%d%d",&u,&a,&b);
for(int i = a;i<=b;i++)
unreach[u][i]=1;
}
for(int i = 1;i<=n;i++)
{
f[i]=dijkstra(1,i);
for(int j = 2;j<i;j++)
{
f[i]=min(f[i],f[j]+dijkstra(j+1,i)+k);
}
}
printf("%d\n",f[n]);
}
Problem E
此题来自某位学长的友情赞助,是给你们的签到题
- 思路
先把数组a全部赋值为-1,表示数组的这个数未分组。然后一个个数字扫进来,如果这个数字没有分组的话,我们找到这个组的范围max(0,p-k+1)~p,如果前面的最小数字未分组或者分组的情况使它自己的话,我们就从前面最小的数字到p分组为最小的数字。
- AC代码
#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
int main()
{
int a[257],n,k;
for (int i = 0; i < 257; i++) a[i] = -1;
scanf("%d %d", &n, &k);
for (int i = 0; i < n; i++)
{
int p;
scanf("%d", &p);
if (a[p] == -1)
{
for (int j = max(0, p - k + 1); j <= p; j++)
{
if (a[j] == -1 || a[j] == j)
{
for (int k = j; k <= p; k++)
a[k] = j;
break;
}
}
}
printf("%d", a[p]);
if (i != n - 1) printf(" ");
else printf("\n");
}
return 0;
}
Problem F
- 思路
二分一下边权。然后跑最小生成树判断即可。
- AC代码
#include<iostream>
#include<cstdio>
#define N 10010
using namespace std;
struct use{int st,en,v1,v2;}e[N*3];
int n,ans,cnt,l,r,m,k,x,y,v,w,fa[N];
int find(int x){if (x!=fa[x]) fa[x]=find(fa[x]);return fa[x];}
bool check(int x){
int temp(0);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=cnt;i++)
if (e[i].v1<=x){
int r1=find(e[i].st),r2=find(e[i].en);
if (r1!=r2){fa[r1]=r2;temp++;}
}
if (temp<k) return false;
for (int i=1;i<=cnt;i++)
if (e[i].v2<=x){
int r1=find(e[i].st),r2=find(e[i].en);
if (r1!=r2){fa[r1]=r2;temp++;}
}
if (temp!=n-1) return false;
return true;
}
int main(){
scanf("%d%d%d",&n,&k,&m);
for (int i=1;i<=m;i++){
scanf("%d%d%d%d",&x,&y,&v,&w);
e[++cnt].st=x;e[cnt].en=y;e[cnt].v1=v;e[cnt].v2=w;
}
l=1;r=30000;
while(l<=r){
int mid=(l+r)>>1;
if (check(mid)) r=mid-1;
else l=mid+1;
}
cout<<l<<endl;
}
2018HUAS_ACM暑假比赛5题解的更多相关文章
- FJUT2019暑假周赛一题解
A.排队问题*-* 题意就是有长度为L的序列,每位的取值可以是'f'或者'm',问不包含'fff'和'fmf'的个数. 打表找规律 不难找出递推公式为F[n] = F[n-1] + F[n-3] + ...
- 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)
这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...
- 纪中OJ 2019.02.15【NOIP提高组】模拟 B 组 梦回三国 比赛题解(第一个)
声明 旁边的同学小 H(胡)对我说: “哟,比赛拿了 140,强!要知道,如果哥第三题 AC 了,哥就 230 了,你个废柴!!!(比赛实际分数 130 额呵)” 顿时,千万草泥马从我心中奔腾而过:你 ...
- ECJTUACM16 Winter vacation training #4 题解&源码
A......................................................................................... 题目链接→Code ...
- Nowcoder | [题解-N189]牛客OI赛制测试赛3
这场说实话确实水(逃*1),表示差一点就AK了(逃*2),然而被卡两个特判的我\(ssfd\)...\(qwq\) 表示这是第一次发整场比赛的题解...还请各位大佬原谅我太蒻写的垃圾啊\(qwq\). ...
- 年少和 Smart の日常比赛 R3
在洛谷上参加了个比赛....写写题解 rank3....共5人...(捂脸 没有注明是官方代码的均是我比赛时本人提交的代码 T1 洗牌 题目描述 小明把 n (n 为偶数)张牌按编号顺序 1, 2, ...
- Codeforces Round #469 Div. 2题解
A. Left-handers, Right-handers and Ambidexters time limit per test 1 second memory limit per test 25 ...
- Codeforces Round #382 Div. 2【数论】
C. Tennis Championship(递推,斐波那契) 题意:n个人比赛,淘汰制,要求进行比赛双方的胜场数之差小于等于1.问冠军最多能打多少场比赛.题解:因为n太大,感觉是个构造.写写小数据, ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
随机推荐
- git 修改已提交了的备注信息的方法
git 修改已提交了的备注信息的方法: 1.当我们已通过 git commit -m '已提交的最新的备注' 命令将代码提交到了缓存区,或者进一步执行了 git push origin master ...
- Github上如何添加 LICENSE 文件?
什么是开源软件? 开源软件是所有人都可以修改和补充的软件,因为开源软件的 license 协议允许这样做. Git版本控制系统就是开源的软件. 实际上开源软件的一个重要组成部分就是添加 license ...
- openstack核心组件——cinder存储服务(11)
一.cinder 介绍: 理解 Block Storage 操作系统获得存储空间的方式一般有两种: 通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘,然后分区.格式化.创建文件系 ...
- ribbon源码(6) Server
Server 代表一个服务器信息. 内部有服务器地址(host).服务器端口(port).服务器dc(zone).是否存活标志(isAliveFlag).请求协议(scheme).是否可以提供服务(r ...
- flask-session、数据库连接池
flask-session 作用:将默认保存的签名cookie中的值保存到redis/memcached/file/Mongodb/SQLAlchemy 安装:pip3 install flask-s ...
- C# 9.0 新特性预览 - 顶级语句
C# 9.0 新特性预览 - 顶级语句 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它们 ...
- pwnable.kr-cmd1-witeup
执行分析程序,知过滤掉了flag.sh.tmp字段,但在linux下可通过通配符匹配文件哦. 哦对,参数输入的命令中,没有环境变量的支持,所有文件和命令必须用绝对路径哦.
- 听我的,看完这30道MySQL基础题再去面试
可以微信搜索公众号「 后端技术学堂 」回复「1024」获取50本计算机电子书,回复「进群」拉你进读者技术交流群,文章每周持续更新,我们下期见! 一个典型的互联网产品架构包含接入层.逻辑处理层以及存储层 ...
- 划重点!AWS的湖仓一体使用哪种数据湖格式进行衔接?
此前Apache Hudi社区一直有小伙伴询问能否使用Amazon Redshift查询Hudi表,现在它终于来了. 现在您可以使用Amazon Redshift查询Amazon S3 数据湖中Apa ...
- JS中的DOM对象
DOM对象 1. DOM树 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model),通过 HTML DOM对象,可访问 JavaScript HTML 文档的所有 ...