noip模拟34 solutions

我从来不为失败找借口,因为败了就是败了,没人听你诉说任何事情

今天很伤感,以来考试没考好,二来改题改半天也改不出来

这次算是炸出来了我经常范的一些错误,比如除以0

一共只有25pts,是我模拟考试以来最最最惨的成绩了吧

T1 Merchant

好像考场上的时候没有太想好思路就开始打了。。。。。。

二分这个不用说,一眼就是二分。。。。

一开始码了一个01背包用来判断,复杂度\(\mathcal{O(n^2logn)}\)

后来发现不对,我好像直接取前m个最大的就好了,复杂度\(\mathcal{O(nlog^2n)}\)

这个就是我考场上的22pts代码,为啥,因为我除以0,直接段错误了

考场下,我直接想起来 nth_element ,这玩意可以\(\mathcal{O(n)}\)求前m大的数啊

然后我直接把sort换成它,WA 44pts,为啥,因为我没有将负数赋值为0

如果前m个数中有负数,我完全可以不加他,所以要和0取max

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e6+5;
ll n,m,s,maxn;
ll k[N],b[N],no[N];
ll f[N],bb[N];
bool check(ll x){
for(re i=1;i<=n;i++){
no[i]=k[i]*x+b[i];
no[i]=max(no[i],0ll);
}
nth_element(no+1,no+n-m+1,no+n+1);
ll tmp=0;
for(re i=n;i>=n-m+1;i--){
tmp+=no[i];
if(tmp>=s)return true;
}
return false;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&s);
bool flag=false;
for(re i=1;i<=n;i++){
scanf("%lld%lld",&k[i],&b[i]);
bb[i]=b[i];
}
sort(bb+1,bb+n+1);
ll tmp=0;
for(re i=n;i>=n-m+1;i--){
tmp+=bb[i];
if(tmp>=s)flag=true;
}
ll l=0,r=1000000000ll,mid;
while(l<r){
mid=l+r>>1;
if(check(mid))r=mid;
else l=mid+1;
}
printf("%lld",r);
}


T2 Equation

这个吧我考场上想到了一种线段树+树剖的做法。

这个做法吧是通过两个式子的加减实现的,记录非常的麻烦,而且还带两个log

码长270,为了祭奠如此之长的代码,我特地把他粘在这里

0pts

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e6+5;
int n,q;
int to[N],nxt[N],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
ll val[N],len[N];
int siz[N],son[N],fa[N],dep[N],top[N];
int dfn[N],cnt,idf[N];
void dfs_fi(int x){
siz[x]=1;son[x]=0;
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
dep[y]=dep[x]+1;
dfs_fi(y);
siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
}
}
void dfs_se(int x,int f){
top[x]=f;dfn[x]=++cnt;idf[cnt]=x;
if(son[x])dfs_se(son[x],f);
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==son[x])continue;
dfs_se(y,y);
}
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
struct XDS{
#define ls x<<1
#define rs x<<1|1
ll tr[N];
bool typ[N],tyq[N];
bool tp[N],tq[N];
bool rep,req;
void pushup(int x){
if(tyq[ls]&&typ[rs]){
typ[x]=typ[ls];
tyq[x]=!tyq[rs];
tr[x]=tr[ls]-tr[rs];
return ;
}
if(!tyq[ls]&&!typ[rs]){
typ[x]=!typ[ls];
tyq[x]=tyq[rs];
tr[x]=tr[rs]-tr[ls];
return ;
}
if(tyq[ls]&&!typ[rs]){
typ[x]=typ[ls];
tyq[x]=tyq[rs];
tr[x]=tr[ls]+tr[rs];
return ;
}
if(!tyq[ls]&&typ[rs]){
typ[x]=typ[ls];
tyq[x]=tyq[rs];
tr[x]=tr[ls]+tr[rs];
return ;
}
}
void build(int x,int l,int r){
if(l==r){
typ[x]=tyq[x]=true;
tr[x]=val[idf[l]];
return ;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(x);
return ;
}
void ins(int x,int l,int r,int pos,ll v){
if(l==r){
typ[x]=tyq[x]=true;
tr[x]=v;
return ;
}
int mid=l+r>>1;
if(pos<=mid)ins(ls,l,mid,pos,v);
else ins(rs,mid+1,r,pos,v);
pushup(x);
return ;
}
ll query(int x,int l,int r,int ql,int qr){
if(ql>qr)return 0;
if(ql<=l&&r<=qr){
tp[x]=typ[x];
tq[x]=tyq[x];
return tr[x];
}
int mid=l+r>>1;
ll tmp1=0,tmp2=0;
if(ql<=mid)tmp1=query(ls,l,mid,ql,qr);
if(qr>mid)tmp2=query(rs,mid+1,r,ql,qr);
if(!tmp1){
tp[x]=tp[rs];tq[x]=tq[rs];
return tmp2;
}
if(!tmp2){
tp[x]=tp[ls];tq[x]=tq[ls];
return tmp1;
}
if(tq[ls]&&tp[rs]){
tp[x]=tp[ls];tq[x]=!tq[rs];
return tmp1-tmp2;
}
if(!tq[ls]&&!tp[rs]){
tp[x]=!tp[ls];tq[x]=tq[rs];
return tmp2-tmp1;
}
tp[x]=tp[ls];tq[x]=tq[rs];
return tmp1+tmp2;
}
#undef ls
#undef rs
}xds;
bool rxp,rxq,ryp,ryq;
ll get_this(int x,int y){
rxp=false;rxq=true;
ryp=false;ryq=true;
ll rex=0,rey=0;
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]]){
int tmp=xds.query(1,1,n,dfn[top[x]],dfn[x]);
if(xds.tq[1]&&rxp){
rxp=xds.tp[1];rxq=!rxq;
rex=tmp-rex;
}
else if(!xds.tq[1]&&!rxp){
rxp=!xds.tp[1];rxq=rxq;
rex=rex-tmp;
}
else {
rxp=xds.tp[1];rxq=rxq;
rex+=tmp;
}
x=fa[top[x]];
}
else{
int tmp=xds.query(1,1,n,dfn[top[y]],dfn[y]);
if(xds.tq[1]&&ryp){
ryp=xds.tp[1];ryq=!ryq;
rey=tmp-rey;
}
else if(!xds.tq[1]&&!ryp){
ryp=!xds.tp[1];ryq=ryq;
rey=rey-tmp;
}
else {
ryp=xds.tp[1];ryq=ryq;
rey+=tmp;
}
y=fa[top[y]];
}
}
if(dep[x]>dep[y]){
int tmp=xds.query(1,1,n,dfn[y]+1,dfn[x]);
if(xds.tq[1]&&rxp){
rxp=xds.tp[1];rxq=!rxq;
rex=tmp-rex;
}
else if(!xds.tq[1]&&!rxp){
rxp=!xds.tp[1];rxq=rxq;
rex=rex-tmp;
}
else {
rxp=xds.tp[1];rxq=rxq;
rex+=tmp;
}
}
else{
int tmp=xds.query(1,1,n,dfn[x]+1,dfn[y]);
//cout<<tmp<<endl;
if(xds.tq[1]&&ryp){
ryp=xds.tp[1];ryq=!ryq;
rey=tmp-rey;
}
else if(!xds.tq[1]&&!ryp){
ryp=!xds.tp[1];ryq=ryq;
rey=rey-tmp;
}
else {
ryp=xds.tp[1];ryq=ryq;
rey+=tmp;
}
}
if(rxp&&ryp){
ryq=!ryq;
return rex-rey;
}
if(!rxp&&!ryp){
rxq=!rxq;
return rey-rex;
}
return rex+rey;
}
signed main(){
scanf("%d%d",&n,&q);
for(re i=2;i<=n;i++){
int x;scanf("%d%lld",&x,&val[i]);
add_edg(x,i);fa[i]=x;
}
dfs_fi(1);dfs_se(1,1);
xds.build(1,1,n);
while(q--){
int ty;
scanf("%d",&ty);
if(ty==1){
int u,v;ll s;
scanf("%d%d%lld",&u,&v,&s);
if(u==v){
ll bi=s/2;
ll now=get_this(1,v);
if(1==v)printf("none\n");
else if(rxq&&ryq)printf("%lld\n",now-bi);
else if(!rxq&&!ryq)printf("%lld\n",-now-bi);
else if(!rxq&&ryq)printf("%lld\n",now+bi);
else printf("%lld\n",-now+bi);
continue;
}
ll tmp=get_this(u,v);
//cout<<dfn[u]<<" "<<dfn[v]<<endl;
//cout<<rxq<<" "<<ryq<<" "<<tmp<<endl;
if(rxq&&ryq&&s==tmp)
printf("inf\n");
else if(rxq&&ryq&&s!=tmp)
printf("none\n");
else {
ll now;
if(rxq&&!ryq){
ll bi=(s+tmp)/2;
now=get_this(1,u);
if(rxq&&ryq)printf("%lld\n",now-bi);
else if(!rxq&&!ryq)printf("%lld\n",-now-bi);
else if(!rxq&&ryq)printf("%lld\n",now+bi);
else printf("%lld\n",-now+bi);
}
else{
ll bi=(s+tmp)/2;
now=get_this(1,v);
if(rxq&&ryq)printf("%lld\n",now-bi);
else if(!rxq&&!ryq)printf("%lld\n",-now-bi);
else if(!rxq&&ryq)printf("%lld\n",now+bi);
else printf("%lld\n",-now+bi);
}
}
}
else{
int u;ll w;
scanf("%d%lld",&u,&w);
xds.ins(1,1,n,dfn[u],w);
}
}
}


但是后来发现其实没有那么复杂,直接利用边权和x1来表示每个点的点权

我们只需要通过奇偶来判断应该加还是减

直接树状数组维护就好了

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e6+5;
int n,q,fa[N];
ll val[N];
int to[N],nxt[N],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int dfn[N],dfm[N],cnt,idf[N];
int dep[N];
void dfs(int x){
dfn[x]=++cnt;
idf[cnt]=x;
for(re i=head[x];i;i=nxt[i]){
int y=to[i];
dep[y]=dep[x]+1;
dfs(y);
}
dfm[x]=cnt;
}
ll tr[N];
int lb(int x){return x&(-x);}
void ins(int x,ll v){
for(re i=x;i<=n;i+=lb(i))
tr[i]+=v;
}
ll query(int x){
ll ret=0;
for(re i=x;i;i-=lb(i))
ret+=tr[i];
return ret;
}
signed main(){
scanf("%d%d",&n,&q);
for(re i=2;i<=n;i++){
scanf("%d%lld",&fa[i],&val[i]);
add_edg(fa[i],i);
}
dfs(1);
for(re i=2;i<=n;i++){
int tmp;
if(dep[i]%2)tmp=-1;
else tmp=1;
ins(dfn[i],val[i]*tmp);
ins(dfm[i]+1,-val[i]*tmp);
}
while(q--){
int typ;
scanf("%d",&typ);
if(typ==1){
int u,v;
ll s;
scanf("%d%d%lld",&u,&v,&s);
ll tmpu=query(dfn[u]);
ll tmpv=query(dfn[v]);
if(dep[u]%2)tmpu=-tmpu;
if(dep[v]%2)tmpv=-tmpv;
if(dep[u]%2==dep[v]%2){
ll tmp=tmpu+tmpv-s;
if(tmp%2)printf("none\n");
else if(dep[u]%2)printf("%lld\n",tmp/2);
else if(dep[v]%2==0)printf("%lld\n",-tmp/2);
}
else{
ll tmp=tmpu+tmpv;
if(tmp==s)printf("inf\n");
else printf("none\n");
}
}
else{
int u,tmp;
ll w;
scanf("%d%lld",&u,&w);
if(dep[u]%2)tmp=-1;
else tmp=1;
ins(dfn[u],-val[u]*tmp);
ins(dfm[u]+1,val[u]*tmp);
val[u]=w;
ins(dfn[u],val[u]*tmp);
ins(dfm[u]+1,-val[u]*tmp);
}
}
}


T3 Rectangle

所以我因为这个题错过了A层????

其实挺伤心的,自己改题总是特别慢,而且思路还总是有偏差

就这个题一开始我想偏了好多,

我用当前的树状数组去更新前面的,而题解是直接将前面的赋值过来

我也是吐了啊,真的很是无奈,最后迫不得已只能去看代码

总而言之就是代码能力过于弱了

这个就是一个用树状数组优化的枚举题;

你发现只有在边界上有点的时候这个正方形才是合法的,

那么我们假装每一列只有一个点,那么我们就可以固定这个点

从这个点向前枚举前面每一列的点,我们如果想用这两列作为矩形的边界

这两个点必须要选上,我们只需要找到那些y特别大特别小的就好了

直接把每个矩形都组合出来

那么如果扩展到多个点的时候,我们只需要根据这两列的点吧整个序列分成几个块就好了

AC_code

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=1e4+5;
const int M=2505;
const ll mod=1e9+7;
int n;
int sca[M][M];
bool vis[M][M];
ll ans;
struct BIT{
ll tr[M];
int lb(int x){return x&(-x);}
void ins(int x,ll v){
for(re i=x;i<=2500;i+=lb(i))
tr[i]+=v;
}
ll query(int x){
ll ret=0;
for(re i=x;i;i-=lb(i))
ret+=tr[i];
return ret;
}
}bit[M],num[M];
signed main(){
scanf("%d",&n);
for(re i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
sca[x][++sca[x][0]]=y;
}
for(re i=1;i<=2500;i++){
sca[i][sca[i][0]+1]=2501;
sort(sca[i]+1,sca[i]+sca[i][0]+1);
}
for(re i=1;i<=2500;i++){
if(!sca[i][0])continue;
for(re j=1;j<=sca[i][0];j++){
vis[i][sca[i][j]]=true;
num[i].ins(sca[i][j],1);
bit[i].ins(sca[i][j],sca[i][j]);
}
for(re j=i-1;j>=1;j--){
if(!sca[j][0])continue;
for(re k=1;k<=sca[j][0];k++){
if(vis[i][sca[j][k]])continue;
vis[i][sca[j][k]]=true;
num[i].ins(sca[j][k],1);
bit[i].ins(sca[j][k],sca[j][k]);
}
int noi=1,noj=1;
int upy=max(sca[i][1],sca[j][1]);
while(sca[i][noi+1]<=upy)noi++;
while(sca[j][noj+1]<=upy)noj++;
while(noi<=sca[i][0]&&noj<=sca[j][0]){
int mx=min(sca[i][noi+1],sca[j][noj+1]);
int mn=min(sca[i][noi],sca[j][noj]);
ll uy=bit[i].query(mx-1)+mod-bit[i].query(upy-1);
ll dy=bit[i].query(mn);
ll us=num[i].query(mx-1)+mod-num[i].query(upy-1);
ll ds=num[i].query(mn);
ans=(ans+(uy*ds%mod+mod-dy*us%mod)%mod*(i-j)%mod)%mod;
upy=mx;
if(sca[i][noi+1]<=mx)noi++;
if(sca[j][noj+1]<=mx)noj++;
}
}
}
printf("%lld",ans);
}


noip模拟34[惨败]的更多相关文章

  1. Noip模拟34 2021.8.9

    T1 Merchant 一眼二分,然后想了想维护凸包,好像并没有什么关系, 然后又想了想维护一个栈,发现跳指针细节过多不想打 最后直接打了二分,大点跑的飞快,感觉比较稳,出来$78$分 是没用神奇的$ ...

  2. 2021.8.9考试总结[NOIP模拟34]

    T1 Merchant 如果$t=0$时不能达到$s$,那么所拿物品的价值一定关于时间单调递增,答案单调.因此可以特判$0$后二分. 用$sort$复杂度被卡,要用$\textit{nth_eleme ...

  3. NOIP模拟34

    考试的时候被T2卡了一年....考虑了一下正解的式子,然后没去给左边分解因数,去给后面乘倍数...理论复杂度O(n^2),实际好像卡不掉的样子.但是由于我智障的打了一棵主席树,他M了.... 预计得分 ...

  4. NOIP模拟 34

    次芝麻,喝喝喝,长寿花! 什么鬼畜题面...一看就不是什么正经出题人 skyh双双双AK了..太巨了... T1 次芝麻 稍稍手玩就能发现分界点以一个优美的方式跳动 然后就愉快地帮次货们次掉了这个题- ...

  5. NOIP 模拟 $34\; \rm Rectangle$

    题解 \(by\;zj\varphi\) 对于没有在同一行或同一列的情况,直接枚举右边界,左边界从大到小,用树状数组维护上下边界即可. 而对于有多个在一列或一行的情况,这些点将左右分成了几个区间,枚举 ...

  6. NOIP 模拟 $34\; \rm Equation$

    题解 \(by\;zj\varphi\) 发现每个点的权值都可以表示成 \(\rm k\pm x\). 那么对于新增的方程,\(\rm x_u+x_v=k\pm x/0\) 且 \(\rm x_u+x ...

  7. NOIP 模拟 $34\; \rm Merchant$

    题解 \(by\;zj\varphi\) 对于选的物品,总值一定有在前一段区间递减,后一段递增的性质,那么就可以二分. check()时只递归归并大的一段,用nth_element即可 Code #i ...

  8. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  9. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

随机推荐

  1. 获取微信公众号的粉丝openid以及用openid获取unionID

    第一步获取微信粉丝的openid https://api.weixin.qq.com/cgi-bin/user/get?access_token=access_token access_token这里 ...

  2. .NET解密得到UnionID

    由于微信没有提供.NET的解码示例代码,自己搜索写了一个,下面的代码是可用的 var decryptBytes = Convert.FromBase64String(encrypdata); var ...

  3. .NET Worker Service 部署到 Linux 作为 Systemd Service 运行

    上一篇文章我们了解了如何将.NET Worker Service 作为 Windows 服务运行,今天我接着介绍一下如何将 Worker Service 部署到 Linux 上,并作为 Systemd ...

  4. 什么是DDoS引导程序IP Stresser?

    1.什么是IP Stresser? IP Stresser是一款用于测试网络或服务器稳健性的工具.管理员可以运行压力测试,从而确定现有资源(带宽.CPU 等)是否足以处理附加负载. 测试个人网络或服务 ...

  5. Burning Bridges 求tarjan求割边

    Burning Bridges 给出含有n个顶点和m条边的连通无向图,求出所有割边的序号. 1 #include <cstdio> 2 #include <cstring> 3 ...

  6. Docker搭建Jenkins+Gogs+Maven/Gradle——代码自动化运维部署平台(三)

    一.简介 1.CI/CD CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法.CI/CD 的核心概念是持续集成.持续交付和持续部署.作为一个面向开发和运营团队的解决方案,CI/C ...

  7. 最新的.NET 热重载介绍

    今天,我们很高兴的向您介绍 Visual Studio 2019 版本 16.11(预览版 1)和 .NET 6 中的 dotnet watch 命令行工具(预览版 4)中的 .NET 热重载体验的可 ...

  8. 【转载】CentOS-yum安装Nginx

    查看系统版本 $ cat /etc/redhat-release Nginx 不在默认的 yum 源中,使用官网的 yum 源 $ rpm -ivh http://nginx.org/packages ...

  9. MySQL中的联表查询与子查询

    0.准备数据 1.内连接:INNER JOIN 2.左连接:LEFT JOIN 3.右连接:RIGHT JOIN 4.USING子句 扩展知识点: 0.表别名的使用: 1.group by的用法 2. ...

  10. 基于redis的分布式锁防止高并发重复请求

    需求: 我们先举个某系统验证的列子:(A渠道系统,业务B系统,外部厂商C系统)(1)B业务系统调用A渠道系统,验证传入的手机.身份证.姓名三要素是否一致.(2)A渠道系统再调用外部厂商C系统.(3)A ...