A.Graph

因为点可以随便走,所以对于每个联通块,答案为边数/2向下取整。

用类似Tarjan的方式,对于每个联通块建立一棵搜索树,尽量让每一个节点的儿子两两配对,如果做不到就用上头顶的天线。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=2e5+5;
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,m;
int to[N<<1],head[N],nxt[N<<1],tot=1,vis[N],yet[N<<1];
vector<int> ans;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot; }
void dfs(int x,int f,int e)
{
if(vis[x])return ;
vis[x]=1;
vector<int> son;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)continue;
dfs(y,x,i);
}
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f||yet[i])continue;
son.push_back(i);
yet[i^1]=1;
}
for(int i=0;i<son.size();i++)
{
if(i&1)ans.push_back(x);
ans.push_back(to[son[i]]);
}
if(son.size()%2)
{
if(e)
{
ans.push_back(x);
ans.push_back(f);
yet[e]=1;
} else ans.pop_back();
}
} int main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++)
if(!vis[i])dfs(i,0,0);
cout<<ans.size()/3<<endl;
int now=0;
for(int i=1;i<=ans.size()/3;i++)
printf("%d %d %d\n",ans[now++],ans[now++],ans[now++]);
return 0;
}

B.Permutatin

从原排列入手比较困难,我们求出这个排列的$pos$数组($pos[a[i]]=i$),那么问题转化为相邻项且绝对值之差$\ge K$的可以交换。最后实际上还是让字典序最小,因为让前面的权值尽量小和权值小的尽量靠前是一样的。

如果在这个序列上有$|pos_i-pos_j|<K,i<j$,那么$pos_i$和$pos_j$的相对位置就已经确定了,相当于是一种限制。不妨把这种限制当作一条有向边,建图跑优先队列拓扑得到结果。

但这样建边时空双炸,因为如果存在$i \rightarrow j, i \rightarrow k,j \rightarrow k$,那么$i \rightarrow k$的边就是无用的。真正需要建的是在两端值域符合条件的下标最小的那两个点。(两段值域分别为$[pos_i-K+1,pos_i-1]$和$[pos_i+1,pos_i+K-1]$)

所以维护一棵权值线段树,每次查询符合条件的最小下标即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
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=5e5+5,M=2e6+2,inf=0x3f3f3f3f;
int n,a[N],pos[N],K,deg[N];
int abss(int x){return x>0?x:-x;}
int to[M],head[N],nxt[M],tot;
priority_queue<int,vector<int>,greater<int> > q;
int ans[N],cnt;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
deg[y]++;
}
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
int minx[N<<2];
void build(int k,int l,int r)
{
minx[k]=inf;
if(l==r)return ;
int mid=l+r>>1;
build(ls(k),l,mid);
build(rs(k),mid+1,r);
minx[k]=min(minx[ls(k)],minx[rs(k)]);
}
void update(int k,int l,int r,int pos,int val)
{
if(l==r){minx[k]=val;return ;}
int mid=l+r>>1;
if(pos<=mid)update(ls(k),l,mid,pos,val);
else update(rs(k),mid+1,r,pos,val);
minx[k]=min(minx[ls(k)],minx[rs(k)]);
}
int ask(int k,int l,int r,int L,int R)
{
if(L>R)return inf;
if(L<=l&&R>=r)return minx[k];
int res=inf;
int mid=l+r>>1;
if(L<=mid)res=min(res,ask(ls(k),l,mid,L,R));
if(R>mid)res=min(res,ask(rs(k),mid+1,r,L,R));
return res;
} int main()
{
n=read();K=read();
for(int i=1;i<=n;i++)
a[i]=read(),pos[a[i]]=i;
build(1,1,n);
for(int i=n;i;i--)
{
int res=ask(1,1,n,pos[i]+1,min(pos[i]+K-1,n));
if(res!=inf)add(pos[i],pos[res]);
res=ask(1,1,n,max(1,pos[i]-K+1),pos[i]-1);
if(res!=inf)add(pos[i],pos[res]);
update(1,1,n,pos[i],i);
}
for(int i=1;i<=n;i++)
if(!deg[i])q.push(i);
while(!q.empty())
{
int x=q.top();q.pop();
ans[x]=++cnt;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
deg[y]--;
if(!deg[y])q.push(y);
}
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}

C.Tree

sb题。答案为边权和。

#include<bits/stdc++.h>
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=1e5+5;
typedef long long ll;
int n;
ll ans=0;
int main()
{
n=read();
for(int i=1;i<n;i++)
{
read();read();ans+=read();
}
cout<<ans<<endl;
return 0;
}

[CSP-S模拟测试62]题解的更多相关文章

  1. csps-s模拟测试62,63Graph,Permutation,Tree,Game题解

    题面:https://www.cnblogs.com/Juve/articles/11631298.html permutation: 参考:https://www.cnblogs.com/clno1 ...

  2. CSP-S 模拟测试94题解

    T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...

  3. CSP-S模拟测试 88 题解

    T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...

  4. CSP-S 模拟测试92 题解

    话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...

  5. CSP-S 模拟测试57题解

    人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...

  6. CSP-S 模拟测试 51 题解

    考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...

  7. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  8. [CSP-S模拟测试110]题解

    也许是最后一篇了. A.最大或 不错的签到题. 对于二进制位来说,高位的一个1比低位的所有1的贡献总和还要大. 显然,$r$必选,因为$r$中所有1的相对考前.那么考虑如何构造另一个数. 首先$l$和 ...

  9. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

随机推荐

  1. BZOJ 3687: 简单题(dp+bitset)

    传送门 解题思路 设\(f(i)\)表示和为\(i\)时的方案数,那么转移方程为\(f(i)+=f(i-x)\),\(x\)为当前枚举到的数字,这样做是\(O(n\sum a_i)\)的,考虑优化.发 ...

  2. 手机上访问angular移动项目

    要实现手机访问本地开发的移动端项目,首先做到两点: 1.本地打开的项目可以使用本地ip访问 2.手机和电脑同时处于一个同一个局域网中(手机和电脑同时连上同一个wifi / 手机开热点给电脑 / 电脑开 ...

  3. ASP.NET免费发送邮件|

    因为之前有做过邮件发送的项目,最近也看一些朋友问起这个的做法,现在拿来给大家查看下.因为那时候是公司的服务器配置的.所以后来自己便在网上找到了一个可以任何个人都是可以使用的邮件发送.小弟新手,高手看到 ...

  4. Java基本数据类型内存分配

    1.java程序运行时有6中地方存储数据,分别是:寄存器.栈.堆.静态存储.常量存储.非RAM(随机存储器),主要是堆与栈的存储.   2.堆与栈是java用来在RAM中存储数据的地方,java自动管 ...

  5. Python笔记(十)_迭代器与生成器

    迭代 用for...in来遍历一个可迭代对象的过程就叫迭代 可迭代对象:列表.元组.字典.集合.字符串.生成器 可以使用内置函数isinstance()判断一个对象是否是可迭代对象 >>& ...

  6. mybatis的一些小细节

    Mybatis要解决的问题: 1. 将sql语句硬编码到java代码中,如果修改sql语句,需要修改java代码,重新编译.系统可维护性不高. 设想如何解决? 能否将sql单独配置在配置文件中. 2. ...

  7. python 自动把mysql备份文件发送邮箱

    import os import time import sched import smtplib from email.mime.text import MIMEText from email.he ...

  8. javaIO流(三)--IO深入操作

    一.字符编码 在计算机的世界中,本质上只认识0,1的字节数据,如果要想描述一些文字的编码就需要对这些二进制的数据进行组合,就需要对二进制的数据进行组合,所以才有了现在可看见的中文显示,但是在进行编码的 ...

  9. luoguP2184 贪婪大陆 题解(树状数组)

    P2184 贪婪大陆  题目 其实很容易理解就是询问一段区间内有多少段不同的区间 然后再仔细思索一下会发现: 1.只要一个区间的开头在一个节点i的左边,那么这个区间包含在区间1~i中. 2.只要一个区 ...

  10. 55.Top K Frequent Elements(出现次数最多的k个元素)

    Level:   Medium 题目描述: Given a non-empty array of integers, return the k most frequent elements. Exam ...