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/颜色问题 题解:算一下每个仆人到它的目的地 ...
随机推荐
- Istio中的流量配置
Istio中的流量配置 目录 Istio中的流量配置 Istio注入的容器 Istio-init istio-proxy Envoy架构 Pilot-agent生成的初始配置文件 Envoy管理接口获 ...
- dubbo学习(三)配置dubbo API方式配置
provider(生产者) import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.Pro ...
- ip子网掩码计算及子网划分
为什么要懂 子网掩码计算,及子网划分属于网络基础知识.一般在几个地方会用到: 公司避免产生网络风暴而划分子网,帮助路由器判断对应主机是否在同一个网段中 服务器相互隔离而划分子网,一般机房管理人员规划: ...
- Linux环境下C++调试的三板斧
调试解决程序的漏洞,是程序员最基本的技能之一.用惯了图形化IDE,在目前使用gtest框架进行单元测试,需要通过xshell远程连接Linux虚拟机进行C++代码的调试时,觉得很不适应.经过几天查资料 ...
- 一篇带你熟悉ansible-playbook剧本
#playbook介绍 #playbook简单介绍 playbook翻译过来就是剧本,以yml/yaml为后缀结尾的一个文本文件 #playbook组成:分为两部分play(定义主机的角色)和task ...
- (转载)Altium Designer 17 (AD17)
转载自:http://blog.csdn.net/qq_29350001/article/details/52199356 以前是使用DXP2004来画图的,后来转行.想来已经有一年半的时间没有画过了 ...
- 基于python的webUI自动化-小白基础篇
最近打算研究一下基于python的webUI自动化,先自学了一下相关基础知识,大概用了一个多月的时间,主要是找视频,一边看视频或者文档一边对照着敲代码运行. 重点强调:一定要一边看一边对照着敲代码运行 ...
- P2947 Look Up S
题目描述: 约翰的N(1≤N≤10^5)头奶牛站成一排,奶牛i的身高是Hi(l≤Hi≤1,000,000).现在,每只奶牛都在向右看齐.对于奶牛i,如果奶牛j满足i<j且Hi<Hj,我们可 ...
- 083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法
083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法 本文知识点:构造方法-带参构造方法 说明:因为时间紧张, ...
- 6个LED的控制
控制任务和要求 让6个LED按要求工作 电路设计 程序设计 1 int Led1 = 1; //各LED与实验板的联接引脚 2 int Led2 = 2; 3 int Led3 = 3; 4 int ...