NOI Online 提高组 题解
来补坑了……
个人认为三道题难度差不多……
还有要说一嘴,为啥我在其他网站代码都好好的,复制到 cnblogs 上 Tab 就成 8 空格了?不过也懒得改了。
T1 序列
首先,遇到这种加一减一还带附加条件的基本都是图论题,所以我们用图论的思维去想这道题。将每个 \(a_i\) 看成一个点,并把每个点赋一个新的权值 \(b_i-a_i\),这样最终就是问是否可以把每个点权变为 \(0\)。
先考虑操作二,对每个操作二的点连无向边建图,同一连通块的点可以互相在总和不变的情况下改变为任意值(因为操作二一个加 \(1\) 一个减 \(1\) 是具有传递性的),于是我们可以把连通块用并查集缩点,当成一个权值不变的点看待。
再考虑操作一,在之前缩点的图上对每个操作一连无向边,建好的图必是二分图或非二分图的情况之一。对于二分图,我们可以在左部点与右部点总和之差不变的前提下修改点权,那要保证答案为YES
则必然要两边相等;对于非二分图,我们仍从二分图的角度去考虑,相当于左部点或右部点内部出现了连边,那么此时其便无法增加或减少奇数值,只能增减偶数值,进而整幅图的总和都无法增减奇数值。那么要保证答案为YES
只能是总和为偶数。
单次复杂度 \(O(n)\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
int n,m,cnt,a[N],b[N],p[N],q[N],fa[N];
bool vis[N];
ll s[N],c[3];
vector<int> G[N];
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
bool dfs(int u,int col)
{
vis[u]=col,c[col]+=s[u];
bool fl=1;
for(int i=0,v;i<G[u].size();++i)
{
if(c[u]==c[v=G[u][i]]) fl=0;
if(!vis[v]&&!dfs(v,3-col)) fl=0;
}
return fl;
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m); cnt=0;
for(int i=1;i<=n;++i) fa[i]=i,G[i].clear(),scanf("%d",a+i);
for(int i=1;i<=n;++i) s[i]=vis[i]=0,scanf("%d",b+i);
for(int i=1,op,x,y;i<=m;++i)
{
scanf("%d%d%d",&op,&x,&y);
if(op==2) fa[find(x)]=find(y);
else p[++cnt]=x,q[cnt]=y;
}
for(int i=1;i<=n;++i) s[find(i)]+=b[i]-a[i];
for(int i=1;i<=cnt;++i)
{
int u=find(p[i]),v=find(q[i]);
G[u].push_back(v);
G[v].push_back(u);
}
bool ok=1;
for(int i=1;i<=n;++i)
if(find(i)==i&&!vis[i])
{
c[1]=c[2]=0;
bool fl=dfs(i,1);
if(fl&&c[1]!=c[2]) {ok=0; break;}
if(!fl&&((c[1]+c[2])&1)) {ok=0; break;}
}
puts(ok?"YES":"NO");
}
return 0;
}
T2 冒泡排序
首先来盘一盘冒泡排序的本质,手玩了几次冒泡排序之后可以很容易发现:一轮冒泡排序就是把每个数的逆序对数减一(如果为零则不用减)。那么我们这道题实际上就是给你一个序列要支持以下操作:单点增减(交换操作实际上只影响了一个点的逆序对个数),全局增减(如果是 \(0\) 则忽略),以及求全局和。忽略 \(0\) 这一个好像不太好搞,但是仍可以用线段树做,比较麻烦,这里不讲。
止步于此,没想出来,遂去无耻地看了题解。其实我们可以用时间为下标维护逆序对个数。具体来说,建立一个树状数组,在 1 号点插入初始序列的逆序对总数,然后再往后的第 \(i+1\) 号点代表了“第 \(i\) 轮冒泡排序后序列的逆序对总数”,这个可以用桶差分 \(O(n\log n)\) 预处理,我们记cnt[i]
为“逆序对个数等于 \(i\) 的数的个数”(比较拗口,别咬到舌头了),那么每一轮(假设为第 \(i\) 轮)要减去的逆序对个数就是所有“逆序对个数大于 \(i\) 的数的个数”(还是比较拗口)。对于询问操作,直接求第 \(k\) 轮后的树状数组前缀和即可。
现在来考虑交换操作。分类讨论,假设要交换 \(a_x\) 与 \(a_{x+1}\),如果交换后 \(a_x<a_{x+1}\),那么实际上初始序列的逆序对个数便要减一,那么这个减一的贡献什么时候消失呢?显然是在第 \(b_{x}+2\) 轮(这里b[]
是记录每个数逆序对个数的数组,\(b_x\) 是已经交换且减一的值),在这里对应的树状数组上把贡献加回来即可。对于 \(a_x>a_{x+1}\) 可采用同样的逻辑分析,这里不再赘述。
复杂度 \(O(n\log n)\)。
#include <bits/stdc++.h>
#define lb(x) (x&(-x))
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,a[N],b[N],cnt[N];
ll tot,c[N];
void add(int x,ll k) {for(;x<=n;x+=lb(x)) c[x]+=k;}
ll ask(int x) {ll res=0; for(;x;x-=lb(x)) res+=c[x]; return res;}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",a+i);
b[i]=i-1-ask(a[i]);
tot+=b[i],++cnt[b[i]];
add(a[i],1);
}
memset(c,0,sizeof(c));
add(1,tot); tot=0;
for(int i=1;i<=n;++i)
{
tot+=cnt[i-1];
add(i+1,-(n-tot));
}
while(m--)
{
int op,x; scanf("%d%d",&op,&x);
x=min(x,n-1);
if(op==1)
{
swap(a[x],a[x+1]);
swap(b[x],b[x+1]);
if(a[x]<a[x+1])
{
--b[x];
add(1,-1);
add(b[x]+2,1);
}
else
{
++b[x+1];
add(1,1);
add(b[x+1]+1,-1);
}
}
else printf("%lld\n",ask(x+1));
}
return 0;
}
T3 最小环
此题不少人说简单,这只是这道题贪心思路好想却不好证所带来的错觉。(也有可能是我真的菜
首先这道题其实是把一堆数分成若干个环(对于每一个 \(k\),有 \(\gcd(n,k)\) 个环,不知道的话可以做 luogu5887 学习一下)。然后对于每一个环就又回到了 \(k=1\) 的情况。
现在面临两个问题:第一,\(n\) 个数该如何分配到这些环中;第二,每个环中的数该如何排布。
对于问题一,我只知道结论:将 \(n\) 个数排序后,连续的一段分到一个环中(\(a_{1\sim n/\gcd(n,k)}\) 在一个环里,其他以此类推)。现在这个结论我只搜到了 EI 的证明,属实没看懂,太菜了,其他人的题解都省略了(摊手.jpg
对于问题二,继续将在环里的 \(p=n/\gcd(n,k)\) 个数排好序,那么环的排布一定是这样(假设 \(p\) 为奇数,偶数情况类似):
\]
证明:使用归纳法。对于 \(p=1,2,3\) 的情况显然成立,现假设对于 \(p=k\) 的情况成立,考虑 \(p=k+1\) 的情况。
现在 \(k\) 个数已排好,考虑将 \(a_{k+1}\) 插入其中。我们把将 \(a_{k+1}\) 插入 \(a_k,a_{k-1}\) 之间的情况与插入任意两个数 \(a_b,a_c\) 的情况做对比,得到
\]
\]
\]
重新移项得
\]
由排序不等式,证毕。
活整完了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,a[N];
ll f[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",a+i),f[0]+=1LL*a[i]*a[i];
sort(a+1,a+n+1);
while(m--)
{
ll ans=0; int k; scanf("%d",&k);
if(!k) {printf("%lld\n",f[k]); continue;}
int p=n/__gcd(n,k);
if(f[p]) {printf("%lld\n",f[p]); continue;}
for(int i=1;i<=n;i+=p)
{
for(int j=0;j<p-2;++j)
ans+=1LL*a[i+j]*a[i+j+2];
ans+=1LL*a[i]*a[i+1]+1LL*a[i+p-1]*a[i+p-2];
}
printf("%lld\n",f[p]=ans);
}
return 0;
}
NOI Online 提高组 题解的更多相关文章
- noip2010提高组题解
NOIP2010提高组题解 T1:机器翻译 题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数. AC做法:直接开1000的队列模拟过程. T2:乌龟棋 题目大意:有长度为n ...
- NOIP 2014 提高组 题解
NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...
- NOIP 2001 提高组 题解
NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...
- NOIP 2000 提高组 题解
NOIP2000 提高组 题解 No 1. 进制转换 https://www.rqnoj.cn/problem/295 水题 对于n和基数r, 每次用n mod r, 把余数按照逆序排列 注意 mod ...
- 【NOIP2018】提高组题解
[NOIP2018]提高组题解 其实就是把写过的打个包而已 道路铺设 货币系统 赛道修建 旅行 咕咕咕 咕咕咕
- NOI On Line 提高组题解
(话说其实我想填的是去年CSP的坑...但是貌似有一道题我还不会写咕咕咕... 先写一下这一次的题解吧. T1:序列.题意省略. 两种操作.这种题要先分析部分分 给出了全部都是2操作的子任务. 发现A ...
- noip2009提高组题解
NOIP2009题解 T1:潜伏者 题目大意:给出一段密文和破译后的明文,一个字母对应一个密文字母,要求破译一段密文,如果有矛盾或有未出现密文无法破译输出failed,否则输出明文. 思路:纯模拟题 ...
- noip2008提高组题解
第一题:笨小猴 模拟 第二题:火柴棒等式 搜索 深搜不用说,确定出两个加数然后判断能否拼出等式. 枚举确实不太好搞,因为枚举范围不确定,太大了容易超时,太小了容易漏解.不过这题的数据貌似很温和,我 ...
- noip2007提高组题解
题外话:这一年的noip应该是最受大众关心的,以至于在百度上输入noip第三个关键字就是noip2007.主要是由于这篇文章:http://www.zhihu.com/question/2110727 ...
随机推荐
- 《Learning to warm up cold Item Embeddings for Cold-start Recommendation with Meta Scaling and Shifting Networks》论文阅读
<Learning to warm up cold Item Embeddings for Cold-start Recommendation with Meta Scaling and Shi ...
- 聊一聊 Spring Boot 中 RESTful 接口设计规范
在设计接口时,有很多因素要考虑,如接口的业务定位,接口的安全性,接口的可扩展性.接口的稳定性.接口的跨域性.接口的协议规则.接口的路径规则.接口单一原则.接口过滤和接口组合等诸多因素,本篇文章将简要分 ...
- SqlServer的order by问题
如果指定了 SELECT DISTINCT,那么 ORDER BY 子句中的项就必须出现在选择列表中.这是我昨天写sql的时候遇到的,主要是因为最近在做一个数据库的迁移与更换,原来MySQL的数据库全 ...
- Siamese network总结
前言: 本文介绍了Siamese (连体)网络的主要特点.训练和测试Siamese网络的步骤.Siamese网络的应用场合.Siamese网络的优缺点.为什么Siamese被称为One-shot分类 ...
- Unity的AnimationCurve
转自:风宇冲Unity3D教程学院http://blog.sina.com.cn/s/blog_471132920101f8nv.html,本文有多处增删减改,详细内容请查看原文. 1.介绍 Anim ...
- 创建Akamai CDN
背景说明: XX全球版项目CDN, 原有改之前:主CDN为Akamai,备CDN为Cloudflare. 计划改之后:主CDN为Cloudflare,备CDN为Akamai. 原因:Akamai CD ...
- lms微服务的rpc通信框架
RPC的概念 RPC 全称 Remote Procedure Call--远程过程调用.是为了解决远程调用服务的一种技术,使得调用者像调用本地服务一样方便透明.简单的说,RPC就是从一台机器(客户端) ...
- Java读取文件创建时间和最后修改时间
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.Input ...
- SpringMVC(9)实现注解式权限验证
对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...
- kafka 安装和配置
转载自:https://www.cnblogs.com/heijinli/p/13545182.html 下载及安装 第一步:进入kafka官网 按照自己的需求选择版本,我这里选择 最新版的 2. ...