不拼尽全力去试一下,又怎么会知道啊

前言

又是被细节问题搞掉的一天。

T1 的话,与正解相差无几,少打了两个 else 一个 ls 打成了 rs,然后就爆零了(本来还有 45pts 的),然后加了一个离散化就 A 了(我裂开)

T2 是写了一个贪心,虽然正确性无法保证,但是个别东西打错了,然后在最后几分钟的时候疯狂的改,结果分数越改越少。

答题的时候发现了一个比较好的打法:每次先开最难的题,打出暴力就走人,然后再去搞别的题。

T1 联

解题思路

线段树裸题,实现上注意一下操作的优先级,以及 if 语句后的 else

显然的,1 和 2 操作对于以前的操作是可以直接覆盖的。

3 操作可以将 1 和 2 操作进行对掉。

同时,对于 \(xor\) 的性质而言,两个 3 操作可以相互抵消。

然后就是区间修改以及区间查询了,注意 laz 标记的下放。

虽然,n的范围是 \(10^{18}\) 但是操作数量是非常有限的。

因此可以离散化,对于每一个边界以及边界的前或者后一个数,以及 1 都要进行离散化,毕竟有用的节点不只是边界。。

code

#include<bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
#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=7e5+110,INF=1e18;
int m,n,tre1[N<<2],tre2[N<<2],laz[N<<2];
int cnt,lsh[N];
struct Ques
{
int opt,l,r;
}q[N];
void push_up(int x)
{
tre1[x]=min(tre1[ls],tre1[rs]);
tre2[x]=min(tre2[ls],tre2[rs]);
}
void build(int x,int l,int r)
{
if(l==r)
{
tre1[x]=l;
tre2[x]=INF;
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
push_up(x);
}
void push_down(int x,int l,int r)
{
if(!laz[x]) return ;
int mid=(l+r)>>1;
if(laz[x]==1)
{
tre1[ls]=tre1[rs]=INF;
tre2[ls]=l;
tre2[rs]=mid+1;
laz[ls]=laz[rs]=1;
laz[x]=0;
return ;
}
if(laz[x]==2)
{
tre2[ls]=tre2[rs]=INF;
tre1[ls]=l;
tre1[rs]=mid+1;
laz[ls]=laz[rs]=2;
laz[x]=0;
return ;
}
if(laz[ls])
{
if(laz[ls]==1)
{
swap(tre1[ls],tre2[ls]);
laz[ls]=2;
}
else if(laz[ls]==2)
{
swap(tre1[ls],tre2[ls]);
laz[ls]=1;
}
else
{
swap(tre1[ls],tre2[ls]);
laz[ls]=0;
}
}
else
{
swap(tre1[ls],tre2[ls]);
laz[ls]=3;
}
if(laz[rs])
{
if(laz[rs]==1)
{
swap(tre1[rs],tre2[rs]);
laz[rs]=2;
}
else if(laz[rs]==2)
{
swap(tre1[rs],tre2[rs]);
laz[rs]=1;
}
else
{
swap(tre1[rs],tre2[rs]);
laz[rs]=0;
}
}
else
{
swap(tre1[rs],tre2[rs]);
laz[rs]=3;
}
laz[x]=0;
}
void update1(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
tre1[x]=INF;
tre2[x]=l;
laz[x]=1;
return ;
}
push_down(x,l,r);
int mid=(l+r)>>1;
if(L<=mid) update1(ls,l,mid,L,R);
if(R>mid) update1(rs,mid+1,r,L,R);
push_up(x);
}
void update2(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
tre1[x]=l;
tre2[x]=INF;
laz[x]=2;
return ;
}
push_down(x,l,r);
int mid=(l+r)>>1;
if(L<=mid) update2(ls,l,mid,L,R);
if(R>mid) update2(rs,mid+1,r,L,R);
push_up(x);
}
void update3(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
if(!laz[x])
{
swap(tre1[x],tre2[x]);
laz[x]=3;
}
else if(laz[x]==1)
{
tre1[x]=l;
tre2[x]=INF;
laz[x]=2;
}
else if(laz[x]==2)
{
tre2[x]=l;
tre1[x]=INF;
laz[x]=1;
}
else
{
swap(tre1[x],tre2[x]);
laz[x]=0;
}
return ;
}
push_down(x,l,r);
int mid=(l+r)>>1;
if(L<=mid) update3(ls,l,mid,L,R);
if(R>mid) update3(rs,mid+1,r,L,R);
push_up(x);
}
void solve()
{
build(1,1,n);
for(int i=1;i<=m;i++)
{
if(q[i].opt==1) update1(1,1,n,q[i].l,q[i].r);
else if(q[i].opt==2) update2(1,1,n,q[i].l,q[i].r);
else if(q[i].opt==3) update3(1,1,n,q[i].l,q[i].r);
printf("%lld\n",lsh[tre1[1]]);
}
}
signed main()
{
m=read();
for(int i=1;i<=m;i++)
{
q[i].opt=read();
q[i].l=read();
q[i].r=read();
lsh[++n]=q[i].l;
lsh[++n]=q[i].r;
lsh[++n]=q[i].l+1;
lsh[++n]=q[i].r+1;
}
lsh[++n]=1;
sort(lsh+1,lsh+n+1);
n=unique(lsh+1,lsh+n+1)-lsh-1;
for(int i=1;i<=m;i++)
{
q[i].l=lower_bound(lsh+1,lsh+n+1,q[i].l)-lsh;
q[i].r=lower_bound(lsh+1,lsh+n+1,q[i].r)-lsh;
}
solve();
return 0;
}

T2 赛

解题思路

首先说明一下贪心做法是错误的,毕竟对于每一种情况我们无法保证选的满足两个人需要的最多就是最优的。

但是可以骗到 70pts

贪心不行,那就暴力枚举呗。

对于所有的物品,我们分为四大类:

  1. 两个人都喜欢的

  2. 第一个人喜欢但是第二个人不喜欢的

  3. 第二个人喜欢但是第一个人不喜欢的

  4. 其它的

我们可以暴力枚举第一类物品的数量,然后对应修改选的第二三类物品的数量。

然后在第四类物品中选择最小的若干个。

对于最小的前几个数可以用动态开点(好像不开也可以)权值线段树来维护。

代码实现细节比较多。。

当然这个题也可以在暴力的基础上三分法搞。

code

70pts的贪心

#include<bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
#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=5e5+10;
int n,m,k,ans,pos,s[N];
int cnt1,cnt2,q1[N],q2[N];
int top,sta[N],res[N];
int t1,t2,s1[N],s2[N];
bool vis[N];
vector<int> v;
bool comp(int x,int y)
{
return s[x]<s[y];
}
signed main()
{
n=read();
m=read();
k=read();
for(int i=1;i<=n;i++)
s[i]=read();
cnt1=read();
for(int i=1;i<=cnt1;i++)
{
q1[i]=read();
vis[q1[i]]=true;
}
cnt2=read();
for(int i=1;i<=cnt2;i++)
{
q2[i]=read();
if(vis[q2[i]]) v.push_back(q2[i]);
else vis[q2[i]]=true;
}
if(k>cnt1||k>cnt2)
{
printf("-1");
return 0;
}
memset(vis,false,sizeof(vis));
for(int i=0;i<v.size();i++)
sta[++top]=v[i];
vector<int>().swap(v);
sort(sta+1,sta+top+1,comp);
for(int i=1;i<=top;i++)
vis[sta[i]]=true;
for(int i=1;i<=cnt1;i++)
if(!vis[q1[i]])
s1[++t1]=q1[i];
for(int i=1;i<=cnt2;i++)
if(!vis[q2[i]])
s2[++t2]=q2[i];
memset(vis,false,sizeof(vis));
sort(s1+1,s1+t1+1,comp);
sort(s2+1,s2+t2+1,comp);
for(pos=1;pos<=2*k-m;pos++)
ans+=s[sta[pos]],vis[sta[pos]]=true;
int pre=pos;
int temp=k-pos+1;
int pos1=1,pos2=1;
if(2*temp>m||pos>top+1)
{
cout<<-1;
return 0;
}
for(int i=1;i<=temp;i++)
{
if(pos==top+1&&pos1==cnt1+1)
{
cout<<-1;
return 0;
}
if(pos==top+1)
{
vis[s1[pos1]]=true;
ans+=s[s1[pos1]];
pos1++;
continue;
}
if(s[sta[pos]]<=s[s1[pos1]])
{
vis[sta[pos]]=true;
ans+=s[sta[pos]];
pos++;
continue;
}
vis[s1[pos1]]=true;
ans+=s[s1[pos1]];
pos1++;
}
for(int i=pos-pre+1;i<=temp;i++)
{
if(pos==top+1&&pos2==cnt2+1)
{
cout<<-1;
return 0;
}
if(pos==top+1)
{
vis[s2[pos2]]=true;
ans+=s[s2[pos2]];
pos2++;
continue;
}
if(s[sta[pos]]<=s[s2[pos2]])
{
vis[sta[pos]]=true;
ans+=s[sta[pos]];
pos++;
continue;
}
vis[s2[pos2]]=true;
ans+=s[s2[pos2]];
pos2++;
}
int cnt=0;
for(int i=1;i<=n;i++)
if(!vis[i])
res[++cnt]=i;
sort(res+1,res+cnt+1,comp);
if(cnt<m-pos1-pos2-pos+3)
{
cout<<-1;
return 0;
}
for(int i=1;i<=m-pos1-pos2-pos+3;i++)
ans+=s[res[i]];
printf("%lld",ans);
return 0;
}

正解

#include<bits/stdc++.h>
#define int long long
#define ls tre[x].l
#define rs tre[x].r
#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=5e5+10,INF=1e18;
int n,m,k,ans,pos,tot,root,s[N];
int cnt1,cnt2,q1[N],q2[N];
int top,cnt,lsh[N],sta[N];
int t1,t2,t3,s3[N],s1[N],s2[N];
bool vis[N];
vector<int> v;
bool comp(int x,int y)
{
return s[x]<s[y];
}
struct VOP_Segment_Tree
{
int l,r,siz,dat;
}tre[N*80];
void push_up(int x)
{
tre[x].dat=tre[ls].dat+tre[rs].dat;
tre[x].siz=tre[ls].siz+tre[rs].siz;
}
void insert(int &x,int l,int r,int pos,int val)
{
if(!x) x=++tot;
if(l==r)
{
tre[x].dat+=val*lsh[l];
tre[x].siz+=val;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) insert(ls,l,mid,pos,val);
else insert(rs,mid+1,r,pos,val);
push_up(x);
}
int query(int x,int l,int r,int rk)
{
if(rk<=0) return 0;
if(l==r) return tre[x].dat;
int mid=(l+r)>>1;
if(rk<=tre[ls].siz) return query(ls,l,mid,rk);
return tre[ls].dat+query(rs,mid+1,r,rk-tre[ls].siz);
}
signed main()
{
n=read();
m=read();
k=read();
for(int i=1;i<=n;i++)
lsh[i]=s[i]=read();
cnt1=read();
for(int i=1;i<=cnt1;i++)
{
q1[i]=read();
vis[q1[i]]=true;
}
cnt2=read();
for(int i=1;i<=cnt2;i++)
{
q2[i]=read();
if(vis[q2[i]]) sta[++top]=q2[i];
else vis[q2[i]]=true;
}
if(cnt1<k||cnt2<k||top<2*k-m)
{
cout<<-1;
return 0;
}
sort(sta+1,sta+top+1,comp);
sort(lsh+1,lsh+n+1);
cnt=unique(lsh+1,lsh+n+1)-lsh-1;
for(int i=1;i<=n;i++)
s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh;
memset(vis,false,sizeof(vis));
top=min(top,m);
for(int i=1;i<=top;i++)
vis[sta[i]]=true;
for(int i=1;i<=cnt1;i++)
if(!vis[q1[i]]) s1[++t1]=q1[i],vis[q1[i]]=true;
for(int i=1;i<=cnt2;i++)
if(!vis[q2[i]]) s2[++t2]=q2[i],vis[q2[i]]=true;
sort(s1+1,s1+t1+1,comp);
sort(s2+1,s2+t2+1,comp);
for(int i=1;i<=top;i++)
ans+=lsh[s[sta[i]]];
for(int i=1;i<=k-top;i++)
ans+=lsh[s[s1[i]]]+lsh[s[s2[i]]];
for(int i=k-top+1;i<=t1;i++)
vis[s1[i]]=false;
for(int i=k-top+1;i<=t2;i++)
vis[s2[i]]=false;
for(int i=1;i<=n;i++)
if(!vis[i])
insert(root,1,cnt,s[i],1);
int sum=ans;
ans+=query(1,1,cnt,m-2*k+top);
for(int i=top-1;i>=0;i--)
{
if(i<2*k-m) break;
if(k-i>cnt1||k-i>cnt2) break;
sum-=lsh[s[sta[i+1]]];
insert(root,1,cnt,s[sta[i+1]],1);
if(k-i<1) continue;
sum+=lsh[s[s1[k-i]]]+lsh[s[s2[k-i]]];
insert(root,1,cnt,s[s1[k-i]],-1);
insert(root,1,cnt,s[s2[k-i]],-1);
ans=min(ans,sum+query(1,1,cnt,m-2*k+i));
}
printf("%lld",ans);
return 0;
}

T3 题

解题思路

非常妙的一个题。。。

首先,每个人挑选的顺序不同,答案是不同的。

正着枚举不是特别好判断两者是否能共存,因此我们选择逆推。

对于每两个不能同时存在的状态,是可以递推到这两个节点和其它节点的。

类似于路径压缩一类的东西。

对于三者之间的共存关系,因为是逆推,如果当前扫到的“边”的两个连接点

如果两个点与现在扫到的节点都不可以共存,那么显然这个节点是无法存活到最后的。

如果当前连边的两个节点中有一个节点是无法与当前扫到节点共存的话,那么另一个节点也不可以。

最后对于答案统计的时候需要用到集合之间的交集,可以用 bitset 维护。

code

#include<bits/stdc++.h>
#define int long long
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=410,M=5e4+10;
int n,m,ans;
bitset<N> f,g[N];
struct Node
{
int x,y;
void insert()
{
x=read();
y=read();
}
}s[M];
signed main()
{
n=read();
m=read();
for(int i=1;i<=m;i++)
s[i].insert();
for(int i=1;i<=n;i++)
{
g[i][i]=true;
for(int j=m;j>=1;j--)
{
if(g[i][s[j].x]&&g[i][s[j].y])
{
f[i]=true;
break;
}
if(g[i][s[j].x]||g[i][s[j].y])
g[i][s[j].x]=g[i][s[j].y]=true;
}
}
for(int i=1;i<=n;i++)
if(!f[i])
for(int j=1;j<i;j++)
if(!f[j]&&!(g[i]&g[j]).count())
ans++;
printf("%lld",ans);
return 0;
}

7.22考试总结(NOIP模拟23)[联·赛·题]的更多相关文章

  1. noip模拟23[联·赛·题]

    \(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...

  2. 5.22考试总结(NOIP模拟1)

    5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...

  3. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  4. 2021.9.22考试总结[NOIP模拟59]

    T1 柱状图 关于每个点可以作出两条斜率绝对值为\(1\)的直线. 将绝对值拆开,对在\(i\)左边的点\(j\),\(h_i-i=h_j-j\),右边则是把减号换成加号. 把每个点位置为横坐标,高度 ...

  5. NOIP 模拟 $23\; \rm 赛$

    题解 将所有物品分成四类,分别为两人共同喜欢的,只有一人喜欢的,没人喜欢的. 首先,先从两人共同喜欢的物品里找出 \(k\) 个,这时,就要从剩余的找出 \(\rm m-k\) 个,而且是最小的. 用 ...

  6. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

  7. 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]

    6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...

  8. 20165237 2017-2018-2 《Java程序设计》第四周考试补做及2-3章编程题

    20165237 2017-2018-2 <Java程序设计>第四周考试补做及2-3章编程题 测试JDB: 用JDB调试上一个程序,输入1.2.3: 2-3章编程题代码托管 (程序的运行结 ...

  9. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  10. 2021.7.29考试总结[NOIP模拟27]

    T1 牛半仙的妹子图 做法挺多的,可以最小生成树或者最短路,复杂度O(cq),c是颜色数. 我考场上想到了原来做过的一道题影子,就用了并查集,把边权排序后一个个插入,记录权值的前缀和,复杂度mlogm ...

随机推荐

  1. android 找不到设备

    前言 当我们安装android studio的时候,测试的时候,你可能找不到设备. 我遇到的有两种情况,一种是本身就需要安装插件,如一些低端机或者有些小米机. 还有一种情况需要去触发一下,有些华为手机 ...

  2. 【pytorch学习】之概率

    6 概率 简单地说,机器学习就是做出预测.根据病人的临床病史,我们可能想预测他们在下一年心脏病发作的概率.在飞机喷气发动机的异常检测中,我们想要评估一组发动机读数为正常运行情况的概率有多大.在强化学习 ...

  3. 客户端单元测试实践——C++篇

    简介: 我们团队在手淘中主要负责BehaviX模块,代码主要是一些逻辑功能,很少涉及到UI,为了减少双端不一致问题.提高性能,我们采用了将核心代码C++化的策略.由于团队项目偏底层,测试同学难以完全覆 ...

  4. Apsara Stack 技术百科 | 数字化业务系统安全工程

    ​简介:数字化平台已经与我们生活紧密结合,其用户规模庞大,一旦系统出现故障,势必会造成一定生活的不便.比如疫情时代,健康码已经成为人们出门必备的条件,一旦提供健康码服务平台出现故障,出行将变得寸步难行 ...

  5. 用python编写向通信产品发送AT指令的程序实例

    一.安装pyserial包pip install pyserial 二.实例代码 # -*- coding: utf-8 -*- import time import hashlib from ser ...

  6. win10 uwp 使用 XamlTreeDump 获取 XAML 树元素内容

    本文来安利大家 XamlTreeDump 库,通过这个库可以将 XAML 树上的元素转换为 json 字符串,可以用来进行 UI 单元测试 开始之前先通过 NuGet 工具安装 XamlTreeDum ...

  7. MQTT GUI 客户端 可视化管理工具

    MQTT GUI 客户端 可视化管理工具 介绍 多标签页管理,同时打开多个连接 提供原生性能,并且比使用 Electron 等 Web 技术开发的同等应用程序消耗的资源少得多 支持 MQTT v5.0 ...

  8. WSL2使用桥接网络,并指定IP

    前言 微软终于解决了宇宙级难题了,一直以来的WSL2每次启动IP都是动态分配的,并且是NAT的网络.当然网上对此也有一些解决方案,编写脚本在启动时修改,但是太麻烦了,这次很完美的解决了这个难题. 检查 ...

  9. 【2023微博签到爬虫】用python爬上千条m端微博签到数据

    一.爬取目标 大家好,我是 @马哥python说,一枚10年程序猿. 今天分享一期python爬虫案例,爬取目标是新浪微博的微博签到数据,字段包含: 页码,微博id,微博bid,微博作者,发布时间,微 ...

  10. PyTorch的安装与使用

    技术背景 PyTorch是一个非常常用的AI框架,主要归功于其简单易用的特点,深受广大科研人员的喜爱.在前面的一篇文章中我们介绍过制作PyTorch的Singularity镜像的方法,这里我们单独抽出 ...