[CSP-S模拟测试45]题解
开局一行$srand$,得分全靠随机化。
A.kill
发现两个并不显然的性质:
1.选中的人和怪物一定是按顺序的。第一个人打所有被选中怪物的第一只,第二个人打第二只,$etc$。
2.最优方案打的怪物一定是一段连续的区间。(因为过去再反方向回来到任务点一定不优)
所以直接枚举第一个打哪只怪即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=5005;
int p[N],q[N],n,m,s,vis[N];
ll ans=1e15;
int abss(int x)
{
return x>0?x:-x;
}
ll cost(int i,int j)
{
return 1LL*(1LL*abss(p[i]-q[j])+1LL*abss(s-q[j]));
}
int main()
{
n=read();m=read();s=read();
for(int i=1;i<=n;i++)
p[i]=read();
for(int i=1;i<=m;i++)
q[i]=read();
sort(p+1,p+n+1);sort(q+1,q+m+1);
for(int i=1;i<=m;i++)
{
ll tmp=0;
for(int j=1;j<=n;j++)
tmp=max(tmp,cost(j,i+j-1));
ans=min(ans,tmp);
}
cout<<ans<<endl;
return 0;
}
B.beauty
直接考虑点对显然没有前途(当然可以像我一样结合随机化乱搞得到50分),那么贪心地考虑每条边
令$size[x]$表示$x$的子树里关键点的个数,尽量让子树里和子树外的关键点配对
所以$x$到它父亲的这条边对答案作出的贡献就是$min(size[x],2*K-size[x])$。其实就是看最多能凑子树内外的多少个点对。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,K=60005;
typedef long long ll;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,k,op,node[K];
int to[N<<1],head[N],nxt[N<<1],tot,size[N];
bool key[N];
ll ans;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs(int x,int f)
{
size[x]+=key[x];
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
dfs(y,x);
size[x]+=size[y];
}
ans+=min(size[x],2*k-size[x]);
} int main()
{
n=read();k=read();op=read();
for(int i=1;i<=(k<<1);i++)
node[i]=read(),key[node[i]]=1;
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs(1,0);
cout<<ans<<endl;
return 0;
}
C.weight
先放官方题解:
首先图的某一棵最小生成树求出来,对于树边和非树边分类讨论。
对于一条非树边,我们至少要将它的权值调整到树上这两个端点对应路径边权最大值 -1 才可以,否则我们一定可以
不选这条边。显然,我们调整到这么大也足够了。
对于一条树边,我们关心的显然是两个端点对应的简单路径经过这条树边的那些边,我们最大的可能选择是那些边
中权值最小的边的权值 -1, (否则我们可以选那条最小边而不选这条树边),而我们如果将这条树边的边权调整成那
个值,它也一定还会在最小生成树中。
所以这道题我们可以写一个树链剖分来完成我们上面的各种操作。
然后……也就没什么了。边权化点权,不断插入非树边用树剖动态维护,树边和非树边分别统计答案。
调到吐血……
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=7e4+5,M=1e5+5;
int n,m,op,maxx;
struct edge
{
int s,t,w,id;
friend bool operator < (edge x,edge y)
{
return x.w<y.w;
}
}e[M];
int to[M<<1],head[N],nxt[M<<1],len[M<<1],tot,id[M<<1],chose[M];
int ans[M];
void add(int x,int y,int z,int i)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
len[tot]=z;
id[tot]=i;
}
int fa[N];
int findf(int x)
{
if(x==fa[x])return x;
return fa[x]=findf(fa[x]);
}
void kruskal()
{
sort(e+1,e+m+1);
for(int i=1;i<=n;i++)
fa[i]=i;
int t=0;
for(int i=1;i<=m;i++)
{
int fx=findf(e[i].s),fy=findf(e[i].t);
if(fx!=fy)
{
fa[fx]=fy;
t++;chose[e[i].id]=1;
add(e[i].s,e[i].t,e[i].w,e[i].id);
add(e[i].t,e[i].s,e[i].w,e[i].id);
}
if(t==n-1)break;
}
}
namespace tre
{
int size[N],son[N],top[N],seg[N],rev[N],dep[N],fa[N],num[N],vl[N],idn[N];
void dfs1(int x,int f)
{
size[x]=1;
fa[x]=f;
dep[x]=dep[f]+1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
vl[y]=len[i];idn[y]=id[i];
dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}
}
void dfs2(int x,int y)
{
top[x]=y;seg[x]=++seg[0];rev[seg[0]]=x;
if(son[x])dfs2(son[x],y);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa[x]||y==son[x])continue;
dfs2(y,y);
}
}
int lz[N<<2],val1[N<<2],val2[N<<2];
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
void build(int k,int l,int r)
{
lz[k]=val2[k]=maxx+1;
if(l==r)
{
val1[k]=vl[rev[l]];
return ;
}
int mid=l+r>>1;
build(ls(k),l,mid);
build(rs(k),mid+1,r);
val1[k]=max(val1[ls(k)],val1[rs(k)]);
}
void down(int k)
{
if(lz[k]==maxx+1)return ;
val2[ls(k)]=min(val2[ls(k)],lz[k]);
val2[rs(k)]=min(val2[rs(k)],lz[k]);
lz[ls(k)]=min(lz[ls(k)],lz[k]);
lz[rs(k)]=min(lz[rs(k)],lz[k]);
lz[k]=maxx+1;
}
int query(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)return val1[k];
int mid=l+r>>1,res=0;
if(L<=mid)res=max(res,query(ls(k),l,mid,L,R));
if(R>mid)res=max(res,query(rs(k),mid+1,r,L,R));
return res;
}
int query(int x,int y)
{
int fx=top[x],fy=top[y],res=0;
while(fx!=fy)
{
if(dep[fx]<dep[fy])swap(fx,fy),swap(x,y);
res=max(res,query(1,1,seg[0],seg[fx],seg[x]));
x=fa[fx],fx=top[x];
}
if(dep[x]>dep[y])swap(x,y);
if(seg[x]<seg[y])res=max(res,query(1,1,seg[0],seg[x]+1,seg[y]));
return res;
}
void update(int k,int l,int r,int L,int R,int val)
{
if(L<=l&&R>=r)
{
val2[k]=min(val2[k],val);
lz[k]=min(lz[k],val);
return ;
}
down(k);
int mid=l+r>>1;
if(L<=mid)update(ls(k),l,mid,L,R,val);
if(R>mid)update(rs(k),mid+1,r,L,R,val);
val2[k]=min(val2[ls(k)],val2[rs(k)]);
}
void update(int x,int y,int val)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])swap(fx,fy),swap(x,y);
update(1,1,seg[0],seg[fx],seg[x],val);
x=fa[fx],fx=top[x];
}
if(dep[x]>dep[y])swap(x,y);
if(seg[x]<seg[y])update(1,1,seg[0],seg[x]+1,seg[y],val);
}
void get(int k,int l,int r)
{
if(l==r)
{
ans[idn[rev[l]]]=(val2[k]==maxx+1?-1:val2[k]-1);
return ;
}
down(k);
int mid=l+r>>1;
get(ls(k),l,mid);
get(rs(k),mid+1,r);
}
void Main()
{
dfs1(1,0);dfs2(1,1);
build(1,1,seg[0]);
for(int i=1;i<=m;i++)
{
if(chose[e[i].id])continue;
ans[e[i].id]=query(e[i].s,e[i].t)-1;
update(e[i].s,e[i].t,e[i].w);
}
get(1,1,seg[0]);
}
}
int main()
{
n=read();m=read();op=read();
for(int i=1;i<=m;i++)
{
e[i].s=read(),e[i].t=read(),e[i].w=read();
e[i].id=i;maxx=max(maxx,e[i].w);
}
kruskal();
tre::Main();
for(int i=1;i<=m;i++)
printf("%d ",ans[i]);
putchar('\n');
return 0;
}
[CSP-S模拟测试45]题解的更多相关文章
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- CSP-S 模拟测试94题解
T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...
- CSP-S模拟测试 88 题解
T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...
- CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...
- CSP-S 模拟测试57题解
人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...
- CSP-S 模拟测试 51 题解
考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...
- [CSP-S模拟测试110]题解
也许是最后一篇了. A.最大或 不错的签到题. 对于二进制位来说,高位的一个1比低位的所有1的贡献总和还要大. 显然,$r$必选,因为$r$中所有1的相对考前.那么考虑如何构造另一个数. 首先$l$和 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
- [CSP-S模拟测试96]题解
以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...
随机推荐
- POI 讀取EXCEL
/*** 獲取單元格數值* * @param cell* @return*/private String getCellValue(Cell cell) {String cellValue = &qu ...
- selenium2-java 浏览器的三种弹窗处理
alert弹窗 confirm弹窗 prompt弹窗 点击确定 // 选取警告弹窗 Alert alert=driver.switchTo().alert(); ...
- fatal: early EOF fatal: index-pack failed & Git, fatal: The remote end hung up unexpectedly
https://stackoverflow.com/questions/15240815/git-fatal-the-remote-end-hung-up-unexpectedly https://s ...
- Java + selenium 元素定位(4)之By CSS
这篇我要介绍元素定位的倒数第二个方法啦,就是基于CSS的元素定位.关于一些CSS的知识,我这里就不累赘的讲了,以后可能会单独写一篇关于CSS的介绍.当然个人推荐如果之前完全没有CSS只是储备的,可以选 ...
- python3 zip 与tf.data.Data.zip的用法
###python自带的zip函数 与 tf.data.Dataset.zip函数 功能用法相似 ''' zip([iterator1,iterator2,]) 将可迭代对象中对应的元素打包成一个元祖 ...
- 浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象
最近在着手重构一个java UI桌面项目,发现这个项目在一开始的时候由于需求不明确,以及开发人员对swing框架不熟悉等问题造成了页面代码混乱的情况:为了能够在各个类里都可以拿到其他类的引用去进行相应 ...
- lvm 磁盘扩容
LVM磁盘管理 一.LVM简介 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它由Heinz Mauelshagen在Linux 2.4内核上实现.LVM将一个或多个硬盘 ...
- IIS 部署网站本地可访问,外网无法访问
1,检查防火墙入站规则,查看本地端口状态 cmd 命令:netstat -na 2:远程连接测试 cmd 命令:telnet IP Port ,如:telnet 127.0.0.1 135 ,连接成功 ...
- 九、hibernate的查询(QBC)
QBC:Query By Criteria 条件查询 比较适合组合条件查询 QBC查询 简单查询 创建Criteria对象:Criteria criteria = session.createCrit ...
- JavaScript_基础笔记
javaScript基础:概念:一门客户端脚本语言 运行在客户端浏览器中的,每一个浏览器都有javaScript的解析引擎 脚本语言:不需要编译,直接可以被浏览器解析执行功能区: 可以来增强用户和ht ...