csps-s模拟测试62,63Graph,Permutation,Tree,Game题解
题面:https://www.cnblogs.com/Juve/articles/11631298.html
permutation:
参考:https://www.cnblogs.com/clno1/p/10832579.html
因为原来的数组不好做于是我们想反过来数组,根据交换条件:值相邻且位置差大于等于k,那么在变换后的数组就变成了位置相邻且差值大于等于k。这样的话变换操作变成了,相邻的大于等于k的值临近交换,于是我们注意到因为现在只能临近交换的原因,两个差值小于k的数他们的相对位置不可能发生改变。那么问题就变成了,在只有一些相对位置限制条件下,无限制的可以随意交换位置,求这个数组的最小字典序(原数组字典序最小也是现在数组字典序最小)。那么我们容易想到拓扑排序。
但是如果每个点都想后面差值小于k的点连边的话,这个图会变得十分巨大,时间无法承受。于是我们必循得考虑优化建图:我们注意到像a->b,b->c,a->c这种建图,a->c这条边是不必要的。于是我们想办法避免掉这种无意义的边,所以对于某个点,我们让它向后面的所有限制(即差值小于k)中只向最小的那一个点连边,那么用线段树维护这样的信息,这样就达到优化建图的目的。
这样只向最小的连边为什么是对的呢?借用上面大佬的一句话:倒着加入,显然 p_i 连向 (p_i-k, p_i)∪(p_i, p_i+k)。我们只需要分别连向两个区间中下标最小的那一个即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=5e5+;
int n,k,a[MAXN],pos[MAXN],du[MAXN],ans[MAXN],num=;
vector<int>m[MAXN];
priority_queue<int>q;
int tr[MAXN<<];
void update(int k,int l,int r,int opt,int val){
if(l==r){
tr[k]=min(tr[k],val);
return ;
}
int mid=(l+r)>>;
if(opt<=mid) update(k<<,l,mid,opt,val);
else update(k<<|,mid+,r,opt,val);
tr[k]=min(tr[k<<],tr[k<<|]);
}
int query(int k,int l,int r,int opl,int opr){
if(opl>opr) return 0x3f3f3f3f;
if(opl<=l&&r<=opr) return tr[k];
int mid=(l+r)>>,res=0x3f3f3f3f;
if(opl<=mid) res=min(res,query(k<<,l,mid,opl,opr));
if(opr>mid) res=min(res,query(k<<|,mid+,r,opl,opr));
return res;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;++i){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
memset(tr,0x3f,sizeof(tr));
for(int i=n;i>=;--i){
int p=query(,,n,max(,pos[i]-k+),pos[i]);
if(p<=n) m[pos[i]].push_back(pos[p]),++du[pos[p]];
p=query(,,n,pos[i],min(n,pos[i]+k-));
if(p<=n) m[pos[i]].push_back(pos[p]),++du[pos[p]];
update(,,n,pos[i],i);
}
for(int i=;i<=n;++i){
if(!du[i]) q.push(-i);
}
while(!q.empty()){
int x=-q.top();
q.pop();
ans[x]=++num;
int N=m[x].size();
for(int i=;i<N;++i){
int y=m[x][i];
--du[y];
if(!du[y]) q.push(-y);
}
}
for(int i=;i<=n;++i){
printf("%d\n",ans[i]);
}
return ;
}
tree:
好像是个结论:边权之和就是答案
#include<cstdio>
#define int long long
int n,ans=;
signed main(){
scanf("%lld",&n);
for(int i=,u,v,w;i<n;++i){
scanf("%lld%lld%lld",&u,&v,&w);
ans+=w;
}
printf("%lld\n",ans);
return ;
}
game:
模拟用堆可以有50分
考虑如何优化
我们对于前p个数找出最大值,并开桶统计所有数出现的次数
然后对于一个新加入的点,如果它大于当前的最大值,那么下一个人一定选择新加如的这个点,所以最大值没有变
否则更新新加入的数的次数并更新最大值
考虑到最大值一定不上升,所以复杂度较有保障
但是还是会T,所以我们离散化一下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#define re register
using namespace std;
const int MAXN=;
int n,k,a[MAXN],p,tim[MAXN],cnt,b[MAXN];
signed main(){
scanf("%d%d",&n,&k);
for(re int i=;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+);
cnt=unique(b+,b+n+)-b-;
for(int i=;i<=n;++i) a[i]=lower_bound(b+,b+cnt+,a[i])-b;
while(k--){
scanf("%d",&p);
re long long ans1=,ans2=;
re int maxp=;
for(re int i=;i<=p;++i){
++tim[a[i]];
maxp=max(maxp,a[i]);
}
ans1+=b[maxp];
--tim[maxp];
while(maxp>&&tim[maxp]==) --maxp;
for(re int i=;i<=n;++i){
if(i&){
if(p+<=n){
++p;
if(a[p]>=maxp) ans1+=b[a[p]];
else{
ans1+=b[maxp];
--tim[maxp];
++tim[a[p]];
while(maxp>&&tim[maxp]==) --maxp;
}
}else{
ans1+=b[maxp];
--tim[maxp];
while(maxp>&&tim[maxp]==) --maxp;
}
}else{
if(p+<=n){
++p;
if(a[p]>=maxp) ans2+=b[a[p]];
else{
ans2+=b[maxp];
--tim[maxp];
++tim[a[p]];
while(maxp>&&tim[maxp]==) --maxp;
}
}else{
ans2+=b[maxp];
--tim[maxp];
while(maxp>&&tim[maxp]==) --maxp;
}
}
}
printf("%lld\n",ans1-ans2);
}
return ;
}
csps-s模拟测试62,63Graph,Permutation,Tree,Game题解的更多相关文章
- [CSP-S模拟测试62]题解
A.Graph 因为点可以随便走,所以对于每个联通块,答案为边数/2向下取整. 用类似Tarjan的方式,对于每个联通块建立一棵搜索树,尽量让每一个节点的儿子两两配对,如果做不到就用上头顶的天线. # ...
- [考试反思]1006csp-s模拟测试62:隔断
本来说好的好一场烂一场. 那样的日子结束了,连着烂了两场...幸亏T3傻逼了救我一命不算太惨... T1树上的特殊性质会做但是没有继续想下去就死在错贪心上了还没有过那个点... T2迭代至稳定被我错误 ...
- csp-s模拟测试61砖块, 数字,甜圈题解
题面:https://www.cnblogs.com/Juve/articles/11626350.html 砖块: 直接模拟即可,map统计被覆盖的次数 #include<iostream&g ...
- csp-s模拟测试56Merchant, Equation,Rectangle题解
题面:https://www.cnblogs.com/Juve/articles/11619002.html merchant: 二分答案,贪心选前m大的 但是用sort复杂度不优,会T掉 我们只是找 ...
- csp-s模拟测试54x,y,z题解
题面:https://www.cnblogs.com/Juve/articles/11606834.html x: 并差集,把不能分到两个集合里的元素和并到一起,设连通块个数为cnt,则答案为:$2^ ...
- csp-s模拟测试53u,v,w题解
题面:https://www.cnblogs.com/Juve/articles/11602450.html u: 用差分优化修改 二维差分:给(x1,y1),(x2,y2)加上s: $d[x1][y ...
- 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色
2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...
- csp-s模拟测试99
csp-s模拟测试99 九九归一直接爆炸. $T1$一眼板子. $T2$一眼语文题(语文的唯一一次$120+$是给模拟出来的可知我的语文能力). $T3$一眼普及题. ?? Hours Later 板 ...
- csp-s模拟测试98
csp-s模拟测试98 $T1$??不是我吹我轻松手玩20*20.$T2$装鸭好像挺可做?$T3$性质数据挺多提示很明显? $One$ $Hour$ $Later$ 这$T1$什么傻逼题真$jb$难调 ...
随机推荐
- 2019 牛客多校第一场 F Random Point in Triangle
题目链接:https://ac.nowcoder.com/acm/contest/881/F 题目大意 给定二维平面上 3 个整数表示的点 A,B,C,在三角形 ABC 内随机选一点 P,求期望$E ...
- Android Telephony分析(一) ---- Phone详解
目录: Phone的继承关系与PhoneFactory(GsmCdmaPhone.ImsPhone.SipPhone) Phone进程的启动 Phone对象的初始化(DefaultPhoneNotif ...
- Linux下修改Mysql的用户(root)的密码(转载)
修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password " ...
- WebApi 如何 优雅的 对 输入输出 解密加密
原文:WebApi 如何 优雅的 对 输入输出 解密加密 这不是变态的想法, 这只是对现实需求的转化. 因为有密文, 所以本文不适用于浏览器到服务端的数据交换; 只适用于服务端到服务端的数据传输. 用 ...
- C 二维数组与指针
http://c.biancheng.net/view/2022.html 1. 区分指针数组和数组指针 指针数组:存放指针的数组,如 int *pstr[5] = NULL; 数组中每个元素存放的是 ...
- java 多项式
/****************************************************************************** * Compilation: javac ...
- 【bug】使用element-ui遇到在IE浏览器中点击enter会回到登录页
1.点击el-input框,会回到登录页(IE浏览器) 外层是el-table/el-form/el-input 添加可以解决 <el-form onSubmit="return fa ...
- 线程池ThreadPoolExecutor工作原理
前言 工作原理 如果使用过线程池,细心的同学肯定会注意到,new一个线程池,但是如果不往里面提交任何任务的话,main方法执行完之后程序会退出,但是如果向线程池中提交了任务的话,main方法执行完毕之 ...
- SQL Server - SQL Server/ bcp 工具如何通信
问题-BCP通讯 ref: https://stackoverflow.com/questions/40664708/bcp-cannot-connect-to-aws-sql-server-but- ...
- SQL Server 2008 install
双击sql server 2008的.exe安装文件,进入[SQL Server 安装中心]. 2 点击界面左侧的[安装],然后点击右侧的[全新SQL Server 独立安装或向现有安装添加功能],进 ...