8.5考试总结(NOIP模拟31)[Game·Time·Cover]
我们总是在注意错过太多,却不注意自己拥有多少。
前言
考场上疯狂搞第一题,终于把人给搞没了。。
T1 Game
解题思路
线段树+二分
总体来讲就是用线段树维护三个值:
没有产生贡献的 a(小 B 的牌)
没有产生贡献的 b(小 A 的牌)
产生了的贡献值
对于上面的三个值建一棵权值线段树。
因为要产生贡献,因此,新合并的区间内产生的贡献一定是左区间的 a 右区间的 b 数量的较小值。
然后,对于每一个 a 查找 一个可以配对的最优的 b (如果存在,一定在 a+1 到目前 b 最大值这个区间内)。
如果两者可以产生贡献的话,删去两者之后就会对答案的贡献值减去一
用 muliset 维护剩余的 b 。
因为保证字典序最大,因此在合法区间内查找符合条件的值越大越好。
对于不会产生贡献的 a 二分区间有一些变化,其他的都大同小异了。。
code
#include<bits/stdc++.h>
//#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=1e5+10;
int n,all,sum,root,a[N],b[N];
int cnt,lsh[N<<1];
multiset<int> s;
struct Segment_Tree
{
int l,r,a,b,dat;
}tre[N<<2];
void push_up(int x)
{
int tmp=min(tre[rs].b,tre[ls].a);
tre[x].dat=tre[ls].dat+tre[rs].dat+tmp;
tre[x].a=tre[ls].a+tre[rs].a-tmp;
tre[x].b=tre[ls].b+tre[rs].b-tmp;
}
void insert(int &x,int l,int r,int pos,int num1,int num2)
{
if(!x) x=++all;
if(l==r)
{
tre[x].a+=num1;
tre[x].b+=num2;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) insert(ls,l,mid,pos,num1,num2);
else insert(rs,mid+1,r,pos,num1,num2);
push_up(x);
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
lsh[++cnt]=a[i]=read();
for(int i=1;i<=n;i++)
lsh[++cnt]=b[i]=read();
sort(lsh+1,lsh+cnt+1);
cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(lsh+1,lsh+cnt+1,a[i])-lsh;
b[i]=lower_bound(lsh+1,lsh+cnt+1,b[i])-lsh;
insert(root,1,cnt,a[i],1,0);
insert(root,1,cnt,b[i],0,1);
s.insert(b[i]);
}
sum=tre[root].dat;
for(int i=1;i<=n;i++)
{
insert(root,1,cnt,a[i],-1,0);
int l=a[i]+1,r=*(--s.end()),ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
insert(root,1,cnt,mid,0,-1);
if(tre[root].dat+1==sum){ans=mid;l=mid+1;}
else r=mid-1;
insert(root,1,cnt,mid,0,1);
}
if(ans!=-1)
{
sum--;
insert(root,1,cnt,ans,0,-1);
s.erase(s.find(ans));
printf("%d ",lsh[ans]);
continue;
}
l=1;r=a[i];ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
insert(root,1,cnt,mid,0,-1);
if(tre[root].dat==sum){ans=mid;l=mid+1;}
else r=mid-1;
insert(root,1,cnt,mid,0,1);
}
insert(root,1,cnt,ans,0,-1);
s.erase(s.find(ans));
printf("%d ",lsh[ans]);
}
return 0;
}
T2 Time
解题思路
其实就是选择每一种值中不同位置的数到两侧边界距离最小的值进行统计。
相当与是把 swap 当作了一种距离的操作。。
用双端队列或者线段树进行是维护距离最小的。
用树状数组维护到两边的距离(数字个数)就好了。
OMA 运用强悍的卡常技术发现数据里相同的数不会超过 10 个
于是我的内存直接
不得不说手写队列真香
code
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=1e5+10;
int n,ans,tre[N];
struct Deque
{
int head,tail,num[15];
bool empty(){return head>tail;}
int size(){return tail-head+1;}
int front(){return num[head];}
int back(){return num[tail];}
void clear(){head=1;tail=0;}
void push(int x){num[++tail]=x;}
void pop_front(){head++;}
void pop_back(){tail--;}
};
Deque q;
struct Node
{
int dat,id;
bool friend operator < (Node x,Node y)
{
if(x.dat==y.dat) return x.id<y.id;
return x.dat<y.dat;
}
}s[N];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int num)
{
for(int i=x;i<=n;i+=lowbit(i))
tre[i]+=num;
}
int ask(int x)
{
int temp=0;
for(int i=x;i;i-=lowbit(i))
temp+=tre[i];
return temp;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
{
s[i].dat=read();
s[i].id=i;
add(i,1);
}
sort(s+1,s+n+1);
q.clear();
for(int i=1;i<=n;i++)
{
q.push(s[i].id);
if(s[i].dat==s[i+1].dat) continue;
while(!q.empty())
{
int x=q.front(),y=q.back();
int dis1=ask(x-1),dis2=ask(n)-ask(y);
ans+=min(dis1,dis2);
if(dis1<dis2) add(x,-1),q.pop_front();
else add(y,-1),q.pop_back();
}
q.clear();
}
printf("%d",ans);
return 0;
}
T3 Cover
解题思路
手写队列真不好
快是快了,就是内存有亿点大(3e5*3e5)直接数组越界到飞起。。
因为区间之间仅有包含和不相交的关系,因此可以转化为树形 DP 进行子树合并。
首先对于所有的区间以左端点为第一关键字,右端点为第二关键字进行排序。
然后用一个栈进行维护就可以完成建边的操作了。
树形 DP 的值用 multiset 维护。
进行子树合并的事后,每次取 set 里最大的值进行合并,保证取某一层里最大的值。
然后就没啥了,思路以及打法确实很妙
code
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=3e5+10;
int tot,head[N],ver[N],nxt[N];
int n,sta[N],top,ans;
void add(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
struct Node
{
int l,r,dat;
void insert(){l=read();r=read();dat=read();}
bool friend operator < (Node x,Node y)
{
if(x.l==y.l) return x.r>y.r;
return x.l<y.l;
}
}s[N];
multiset<int> f[N];
void merge(multiset<int> &x,multiset<int> &y)
{
if(x.size()<y.size()) swap(x,y);
queue<int> q;
for(auto it=y.begin();it!=y.end();it++)
{
q.push(*it+*x.begin());
x.erase(x.begin());
}
while(!q.empty())
{
x.insert(q.front());
q.pop();
}
}
void dfs(int x)
{
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
dfs(to);
merge(f[x],f[to]);
}
f[x].insert(-s[x].dat);
}
signed main()
{
n=read();n=read();
for(int i=1;i<=n;i++)
s[i].insert();
sort(s+1,s+n+1);
sta[++top]=0;
for(int i=1;i<=n;i++)
{
while(sta[top]&&s[sta[top]].r<s[i].r) top--;
add(sta[top],i);
sta[++top]=i;
}
dfs(0);
for(int i=1;i<=n;i++)
{
if(f[0].size())
{
ans-=*f[0].begin();
f[0].erase(f[0].begin());
}
printf("%lld ",ans);
}
return 0;
}
8.5考试总结(NOIP模拟31)[Game·Time·Cover]的更多相关文章
- noip模拟31[time·game·cover]
noip模拟31 solutions 我就觉得这些考试题是越考越难,我是也越考越完蛋,已经完完全全的接近爆零了 只有20pts,说真的这还是我第一次挂掉30pts,本来我还有50pts嘞 所以这次考试 ...
- 2021.8.5考试总结[NOIP模拟31]
暴力打满直接rk3? T1 Game 想了一万种贪心和两万种$hack$. 可以先用最显然的贪心求出最高得分是多少.(从小到大用最小的大于$b_i$的$a$得分) 然后用一棵权值线段树维护值域内$a$ ...
- 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]
6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...
- 5.23考试总结(NOIP模拟2)
5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...
- 5.22考试总结(NOIP模拟1)
5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- [考试总结]noip模拟23
因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...
- 「考试」noip模拟9,11,13
9.1 辣鸡 可以把答案分成 每个矩形内部连线 和 矩形之间的连线 两部分 前半部分即为\(2(w-1)(h-1)\),后半部分可以模拟求(就是讨论四种相邻的情况) 如果\(n^2\)选择暴力模拟是有 ...
- 6.11考试总结(NOIP模拟7)
背景 时间分配与得分成反比,T1 20min 73pts,T2 1h 30pts,T3 2h 15pts(没有更新tot值,本来应该是40pts的,算是本次考试中最遗憾的地方了吧),改起来就是T3比较 ...
- 6.10考试总结(NOIP模拟6)
前言 就这题考的不咋样果然还挺难改的.. T1 辣鸡 前言 我做梦都没想到这题正解是模拟,打模拟赛的时候看错题面以为是\(n\times n\)的矩阵,喜提0pts. 解题思路 氢键的数量计算起来无非 ...
随机推荐
- apache 服务器配置常用知识点合集
前言 因为当年周围同学都在学php,最为简单的就是学php 好就业啊,写个一些php,最后放弃了,apache也看了两眼吧.下面是我使用有记录的,没有记录的我后面会补上. 正文 域名配置 1.取消 N ...
- Consul的服务注册与发现(简单介绍)
Consul的注册中心的安装及配置 1.consul下载 2.开发模式启动consul consul agent -dev 3.验证测试 通过以下地址可以访问Consul的首页: http://loc ...
- Vue 项目 invalid host header 问题 配置 disableHostCheck:true报错
项目场景:解决 Vue 项目 invalid host header 问题disableHostCheck:true报错 问题描述使用内网穿透时出现 invalid host header找了好多都是 ...
- 基础 IO (Linux学习笔记)
基础IO 1.重谈文件 空文件在磁盘也要占据空间 文件 = 内容 + 属性 文件操作 = 对文件内容+对属性 or 对文件内容加属性 标定一个文件,必须使用文件路径加文件名[唯一性] 如果没有指明对应 ...
- Java面试题:细数ThreadLocal大坑,内存泄露本可避免
一.背景ThreadLocal是Java中用于解决多线程共享变量导致的线程安全问题的一种机制.它为每个线程分配一个独立的变量副本,从而避免了线程间的数据竞争.这个我们从上一篇文章<Java面试题 ...
- 爱奇艺在 Dubbo 生态下的微服务架构实践
简介: 本文整理自作者于 2020 年云原生微服务大会上的分享<爱奇艺在 Dubbo 生态下的微服务架构实践>,重点介绍了爱奇艺在 Dubbo.Sentinel 等开发框架方面的使用经验以 ...
- 云原生微服务的下一站,微服务引擎 MSE 重磅升级
简介:管好微服务,成为云原生时代的新难题. 管好微服务,成为云原生时代的新难题. 从建好微服务到管好微服务,差的虽是一个字,连接起两边的却需要大量的微服务落地经验.因为软件架构的核心挑战是解决业务快 ...
- 配置审计(Config)配合开启OSS防盗链功能
简介: 本文作者:紫极zj 本文将主要介绍利用[配置审计]功能,如何快速发现企业上云过程中,针对未配置防盗链的 OSS Bucket 定位及修复案例. 前言 配置审计(Config)将您分散在各地域的 ...
- OpenKruise v0.10.0 版本发布:新增应用弹性拓扑管理、应用防护等能力
简介: 阿里云开源的云原生应用自动化管理套件.CNCF Sandbox 项目 -- OpenKruise,今天发布 v0.10.0 新版本,这也会是 OpenKruise v1.0 之前的最后一个 m ...
- [FAQ] jsoneditor 如何切换 mode 或者选择 modes
1. 用于切换编辑器模式:text.tree.code JSONEditor.setMode(mode) 2. 让 mode 变成可以选择的: const options = { modes: ['t ...