A Rooms and Passages

题意

给n个数,从起点出发,一直往右走,遇到一个前面出现过其相反数的正数就停下,问对于每个起点都能走多少步。

分析

  • 倒着递推,如果起点是正数,那么肯定可以走,ans[i]=ans[i+1]+1
  • 如果起点是负数,那就得看这个负数对应绝对值在后面出现的最靠前的位置,而且还要看后面的负数所对应的绝对值的最靠前位置,所以这个lst应该是全局更新的。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+50;
int a[N],n,pos[N],ans[N];
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int lst=n+1;
for(int i=n;i>=1;i--){
if(a[i]>0){
ans[i]=ans[i+1]+1;
pos[a[i]]=i;
}else{
if(!pos[-a[i]]){
ans[i]=ans[i+1]+1;
}else{
lst=min(lst,pos[-a[i]]-1);
ans[i]=lst-i+1;
}
}
}
for(int i=1;i<=n;i++){
printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}

B Rearrange Columns

题意

有两行字符串,有#.,可以对列进行重排,使得#连在一起。

分析

  • 计算两个#,一个#在上面和在下面的,和没有#的,如果没有两个#而且#有上有下的,就不行。
  • 否则,把两个#的放中间即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+55;
char a[2][N];
int main(){
scanf("%s",a[0]);
scanf("%s",a[1]);
int n=strlen(a[0]);
int shang=0;
int xia=0;
int mei=0;
int liang=0;
for(int i=0;i<n;i++){
if(a[0][i]=='#' && a[1][i]=='#'){
liang++;
}else if(a[0][i]=='#' && a[1][i]=='.'){
shang++;
}else if(a[0][i]=='.' && a[1][i]=='#'){
xia++;
}else{
mei++;
}
}
if(liang || (shang &&!xia) || (xia&&!shang)){
printf("YES\n");
for(int i=0;i<mei;i++){
printf(".");
}
for(int i=0;i<shang+liang;i++){
printf("#");
}
for(int i=0;i<xia;i++){
printf(".");
}
printf("\n");
for(int i=0;i<mei;i++){
printf(".");
}
for(int i=0;i<shang;i++){
printf(".");
}
for(int i=0;i<liang+xia;i++){
printf("#");
}
printf("\n");
}else{
printf("NO\n");
}
return 0;
}

C Jumps on a Circle

题意

一个环标记为0到p-1,从0开始每次跳1,2,3...步,问跳n步之后会有多少个位置访问过。

分析

跳min(n,2p)次之后肯定会回到原点然后重新跳1,2,3...,所以模拟即可。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+50;
ll n,p;
int vis[N];
int main(){
scanf("%lld%lld",&p,&n);
vis[0]=1;
ll now=0;
for(ll i=1;i<=min(n,2*p);i++){
now=(now+i)%p;
vis[now]=1;
}
int ans=0;
for(ll i=0;i<p;i++){
ans+=vis[i];
}
printf("%d\n",ans);
return 0;
}

D Country Division

题意

给一棵树,每次询问给一些点染成红色,一些点染成蓝色,问能不能删掉一些边使得同色之间能相互到达,不同色之间不能相互到达。

分析

  • 因为是一棵树,如果可以删的话肯定删一条边就够了。
  • 假设1为根,先求红色点的lca,再求蓝色点的lca,如果两个lca不在同一棵子树,那么删掉其中一个连向父节点的边即可。
  • 如果两个lca有祖先关系,比如红色lca和蓝色lca的lca就是红色lca,那么如果红色点都在红色lca指向蓝色lca的另一条边上,那就可以,否则,说明有红色点在蓝色点的子树下。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
struct Edge{
int v,next;
}e[N*2];
int d[N],fa[N][20],pw[20];
int cnt,head[N];
void init(){
pw[0]=1;
for(int i=1;i<=20;i++){
pw[i]=pw[i-1]*2;
}
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v){
e[cnt]=Edge{v,head[u]};
head[u]=cnt++;
e[cnt]=Edge{u,head[v]};
head[v]=cnt++;
}
void dfs(int u){
for(int i=1;pw[i]<=d[u];i++){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==fa[u][0]){
continue;
}
fa[v][0]=u;
d[v]=d[u]+1;
dfs(v);
}
}
int lca(int x,int y){
if(d[x]<d[y]){
swap(x,y);
}
int tmp=d[x]-d[y];
for(int i=0;pw[i]<=tmp;i++){
if(tmp&pw[i]){
x=fa[x][i];
}
}
if(x==y){
return x;
}
for(int i=19;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int n,q,u,v,ri,bi,x,red[N],blue[N];
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
init();
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(1);
scanf("%d",&q);
while(q--){
scanf("%d%d",&ri,&bi);
scanf("%d",&red[1]);
int rlc=red[1];
for(int i=2;i<=ri;i++){
scanf("%d",&red[i]);
rlc=lca(rlc,red[i]);
}
scanf("%d",&blue[1]);
int blc=blue[1];
for(int i=2;i<=bi;i++){
scanf("%d",&blue[i]);
blc=lca(blc,blue[i]);
}
int lc=lca(rlc,blc);
if(rlc!=lc && blc!=lc){
printf("YES\n");
}else if(rlc==lc){
bool flag=false;
for(int i=1;i<=ri;i++){
if(lca(red[i],blc)==blc){
printf("NO\n");
flag=true;
break;
}
}
if(!flag){
printf("YES\n");
}
}else if(blc==lc){
bool flag=false;
for(int i=1;i<=bi;i++){
if(lca(blue[i],rlc)==rlc){
printf("NO\n");
flag=true;
break;
}
}
if(!flag){
printf("YES\n");
}
}
}
return 0;
}

E Third-Party Software - 2

题意

求最少的线段覆盖整个区间。

分析

贪心经典题。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
struct node{
int l,r,id;
bool operator <(const node& rhs)const{
if(l==rhs.l){
return r>rhs.r;
}else{
return l<rhs.l;
}
}
}a[N];
int n,m;
vector<int> res;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
}
sort(a+1,a+1+n);
int now=1,i=1,ans=0;
while(i<=n && now<=m){
int mx=0;
int k=0;
while(i<=n && a[i].l<=now){
if(a[i].r>mx){
mx=a[i].r;
k=i;
}
i++;
}
if(mx<=now-1){
ans=-1;
break;
}
res.push_back(a[k].id);
now=mx+1;
ans++;
}
if(now<=m){
ans=-1;
}
if(ans==-1){
printf("NO\n");
}else{
printf("YES\n");
printf("%d\n",ans);
for(int i=0;i<ans;i++){
printf("%d%c",res[i],i==ans-1?'\n':' ');
}
}
return 0;
}

F Friendly Fire

题意

n个怪兽,有两个属性a和b,如果属性a大于另一个怪兽的属性b,就可以打死该怪兽,现在要选出两个怪兽同时打,可能同时死,要使死的怪兽的属性a总和最大。

分析

  • 参考了entry上一个外国朋友的思路https://codeforces.com/blog/entry/67178
  • 考虑分别对a和对b递增排序,得到两个序列,然后枚举第一个序列的怪兽,然后把第二个序列中当前怪兽能打败的怪兽的a值加入优先队列中,因为这些怪兽肯定能被打死,所以直接取出最大的a值,然后再看取出的怪兽能否打败枚举的怪兽,再考虑是否再更新答案。
  • 如果取出的怪兽是本身,就取下一个,注意空队列的判断,取出的怪兽如果没用到,continue之前也要重新入队

代码

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+50;
int n;
struct node{
int a,b,id;
}a[N],b[N];
bool cmp1(node a,node b){
if(a.a==b.a){
return a.b<b.b;
}else{
return a.a<b.a;
}
}
bool cmp2(node a,node b){
if(a.b==b.b){
return a.a<b.a;
}else{
return a.b<b.b;
}
}
priority_queue<pair<int,int> > q;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].a,&a[i].b);
a[i].id=i;
b[i]=a[i];
}
sort(a+1,a+1+n,cmp1);
sort(b+1,b+1+n,cmp2);
int ans=0;
int le=0,ri=0;
bool up=false;
for(int i=1,j=1;i<=n;i++){
while(j<=n && b[j].b<=a[i].a){
q.push({b[j].a,j});
j++;
}
if(q.empty()){
continue;
}
int mx=q.top().first;
int idx=q.top().second;
// printf("%d %d %d\n",i,a[i].a,a[i].b);
// printf("%d %d %d %d\n",idx,mx,b[idx].id,a[i].id);
if(b[idx].id==a[i].id){
// printf("%d F\n",i);
auto tmp=q.top();
q.pop();
if(q.empty()){
q.push(tmp);
continue;
}
mx=q.top().first;
idx=q.top().second;
q.push(tmp);
}
int t=mx+(b[idx].a>=a[i].b?a[i].a:0);
if(t>ans){
up=true;
ans=t;
le=a[i].id;
ri=b[idx].id;
}
}
printf("%d\n",ans);
if(!up){
printf("1 2\n");
}else{
printf("%d %d\n",le,ri);
}
return 0;
}

H Missing Number

题意

有0-n一共n+1个数,现在删去一个数,通过交互得到删去的数。

交互是询问第x个数的第i位是0还是1。

分析

  • 先分别询问每个数的最低位,统计1的个数,显然如果不缺数的话,1的个数应该是\(\frac{n+1}{2}\),可以由此判断缺的数这一位是0还是1。

  • 然后可以排除掉一半不符合的数,继续询问第2位。

  • 用set存数字下标(即第几个数)比较好写。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
set<int> ns,t;
int main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
ns.insert(i);
}
//从最低位开始询问
int i=0;
int res;
int ans=0;
while(ns.size()>=1){
int sz=ns.size();
t.clear();
int b=0;
for(auto it=ns.begin();it!=ns.end();it++){
int x=*it;
//询问第x个数的第i位
cout << "? " << x << " " << i << endl;
cout.flush();
cin >> res;
if(res){
t.insert(x);
b++;
}
}
if(b<(sz+1)/2){
//缺少的数第i位为1
ans+=(1<<i);
ns=t;
}else{
for(auto it=t.begin();it!=t.end();it++){
ns.erase(*it);
}
}
i++;
}
cout << "! " << ans << endl;
return 0;
}

I Painting a Square

题意

一个边长为b的小正方形给一个边长为a的大正方形涂色,问最小需要走的步数。

分析

  • 沿着边缘螺旋走进去是最优的。
  • 所以先沿这边缘走两个边长,就转化为a-b的小正方形的情况了。
  • 本地跑不出来所以手动栈模拟,不过评测机上能跑出来。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
ll fun(ll a,ll b){
// printf("%lld %lld\n",a,b);
if(a-b<b){
return 3ll*(a-b);
}else{
return fun(a-b,b)+2ll*(a-b)+b;
}
}
stack<ll>st;
ll solve(ll a,ll b){
ll aa=a;
while(aa-b>=b)
{
st.push(aa);
aa-=b;
}
ll ans=3ll*(aa-b);
while(!st.empty())
{
ans=ans+2ll*(st.top()-b)+b;
st.pop();
}
return ans;
}
int main(){
scanf("%lld%lld",&a,&b);
// ll ans=solve(a,b);
ll ans=fun(a,b);
printf("%lld\n",ans);
return 0;
}

J The Power of the Dark Side - 2

题意

n个人,每人有三种属性,如果有两种属性严格大于的话就能击败另一个人,问对于每个人,如果在每场战斗之前都能随意调整属性值,最多能击败多少人。

分析

  • 考虑每个人能被击败的条件,显然就是对方属性值总和至少有(两个最小的属性值+2)。
  • 所以把每个人能被击败的下限求出来,排序,然后枚举每个人的属性总和,upper_bound()查出能击败的人数,再判断这些人里面是否有自身。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+55;
ll a[N][3];
ll sum[N];
int n;
vector<ll> v;
vector<int> ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&a[i][0],&a[i][1],&a[i][2]);
sum[i]=a[i][0]+a[i][1]+a[i][2];
sort(a[i],a[i]+3);
v.push_back(a[i][0]+a[i][1]+2);
}
sort(v.begin(),v.end());
for(int i=1;i<=n;i++){
int k=upper_bound(v.begin(),v.end(),sum[i])-v.begin();
ll t=sum[i]-(a[i][0]+a[i][1]+2);
if(t>=0){
k--;
}
ans.push_back(k);
}
for(int i=0;i<n;i++){
printf("%d%c",ans[i],i==n-1?'\n':' ');
}
return 0;
}

K Deck Sorting

题意

分析后的题意是给一个只含RGB的字符串,从中抽出一个子序列,和剩下的子序列拼在一起,使得拼接后的字符串相同字符在一起。

分析

  • 枚举6个全排列,也就是拼接后的字符串情况,假设枚举RBG,那么就得把所有R取出。所有G剩下,要考虑的就是B,如果B是在最后一个R的后面,那就是跟随R取出,如果是在第一个G前面,那就跟随G留下,否则,即如果B在最后一个R前面且再第一个G后面,那就是不合法的。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+55;
char s[N];
set<char> lt;
char idx[]={'R','G','B'};
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++){
lt.insert(s[i]);
}
int siz=lt.size();
if(siz<3){
printf("YES\n");
}else{
for(int i=0;i<3;i++){
char le=idx[i];
for(int j=0;j<3;j++){
if(i==j){
continue;
}
char ri=idx[j];
char md=idx[3-i-j];
int leri=-1;
int rile=-1;
for(int k=n;k>=1;k--){
if(s[k]==le){
leri=k;
break;
}
}
for(int k=1;k<=n;k++){
if(s[k]==ri){
rile=k;
break;
}
}
bool flag=true;
for(int k=1;k<=n;k++){
if(s[k]==md){
if(k<leri && k>rile){
flag=false;
break;
}
}
}
if(flag){
printf("YES\n");
return 0;
}
}
}
printf("NO\n");
}
return 0;
}

M Shlakoblock is live!

题意

n个东西有p属性和v属性,现在可以选择将一些东西的v属性加1,求最大的每个东西的p的期望。

分析

p越大,v加1对期望的贡献肯定越大,所以对p排序,然后对v加1,更新答案,直到对答案没有影响就退出。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1050;
int t,n;
struct node{
ll zi,mu;
};
bool cmp(node a,node b){
return a.zi*b.mu>a.mu*b.zi;
}
struct info{
int p,v,id;
bool operator <(const info& rhs)const{
return p>rhs.p;
}
}a[N];
vector<int> ans;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ll zi=0,mu=0;
for(int i=1;i<=n;i++){
scanf("%lld%lld",&a[i].p,&a[i].v);
zi+=a[i].p*a[i].v;
mu+=a[i].v;
a[i].id=i;
}
sort(a+1,a+1+n);
ans.clear();
node tt{zi,mu};
for(int i=1;i<=n;i++){
zi+=a[i].p;
mu++;
node tmp={zi,mu};
if(cmp(tmp,tt)){
ans.push_back(a[i].id);
tt=tmp;
}else{
break;
}
}
ll g=__gcd(tt.zi,tt.mu);
printf("%lld/%lld\n",tt.zi/g,tt.mu/g);
int siz=ans.size();
sort(ans.begin(),ans.end());
printf("%d\n",siz);
if(!siz){
printf("\n");
}
for(int i=0;i<siz;i++){
printf("%d%c",ans[i],i==siz-1?'\n':' ');
}
}
return 0;
}

gym102215题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. oracle11G 同时支持IPV4和IPV6配置

    1.修改listener.ora文件 LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ...

  2. Spring Boot教程(二十六)使用Spring Security安全控制

    准备工作 首先,构建一个简单的Web工程,以用于后续添加安全控制,也可以用之前Chapter3-1-2做为基础工程.若对如何使用Spring Boot构建Web应用,可以先阅读<Spring B ...

  3. getFieldDecorator用法(一)——登录表单

    之前使用antd的ui表单,却没发现这么好用的用法,推荐给大家 import React from "react"; import { Card, Form, Input, But ...

  4. H5自定义video功能与样式处理

    H5的video非常简单,方便,有时我们可能需要自己来设置样式来自定义的video,自定义的话我们需要对功能进行一些处理,这里常用的功能几乎是都用到了,第一次练习代码很累赘,之后会慢慢改进. 常用的一 ...

  5. java取小数点后两位

    package com.yonyou.sud.algorithm; import java.math.BigDecimal;import java.text.DecimalFormat;/*** ja ...

  6. Unit Test in SpringBoot

    此处的Unit Test in SpringBoot 包括: SpringApplication Test Service Test ControllerTest 测试项目结构如下: 代码如下: PO ...

  7. Mac安装ipython与jupyter

    Python从Python发展而来,更倾向于科学计算.互联网数据分析更喜欢用. 首先切换root用户: sudo su - pip3自动安装ipython yuchaodeMacBook-Pro:~ ...

  8. Docker入门-数据挂载

    Docker数据管理 在容器中管理数据主要有两种方式: 数据卷(Volumes) 挂载主机目录(Bind mounts) 数据卷 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很 ...

  9. 远程连接mysql要点 虚拟主机定义与分类

    远程连接mysql:通过主机地址与端口号连接 1. 主机地址:找到主机电脑 2. 端口号:找到对应mysql软件 mysql客户端访问服务端需要进行寻找匹配:连接认证-h 主机地址 例如 -hloca ...

  10. Jmeter+Ant+Jenkins接口自动化持续集成环境搭建(Linux)

    一.安装说明 系统环境:CentOS release 6.4 JDK版本:jdk1.8.0_181 Jmeter版本:apache-jmeter-3.0 Ant版本:apache-ant-1.9.13 ...