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. 并发王者课-铂金6:青出于蓝-Condition如何把等待与通知玩出新花样

    欢迎来到<[并发王者课](https://juejin.cn/post/6967277362455150628)>,本文是该系列文章中的**第19篇**. 在上一篇文章中,我们介绍了阻塞队 ...

  2. ES6学习笔记之字符串新增方法

    1.字符串的子串识别 传统上,Javascript 只有indexof 方法,用来确定一个字符串是否包含在另一个字符串中.如: //indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的 ...

  3. Restful规范-APIView源码分析

    目录 一.Restful规范 十条规范 二.drf的简单使用 三.APIView源码分析 CBV源码分析 APIView源码分析 一.Restful规范 Restful规范是一种web API接口的设 ...

  4. JDK1.8 ArrayList 源码解析

    源码的解读逻辑按照程序运行的轨迹展开 Arraylist的继承&实现关系 打开ArrayList源码,会看到有如下的属性定义, ArrayList中定义的属性 /** * Default in ...

  5. AcWing 1282. 搜索关键词

    给定n个长度不超过50的由小写英文字母组成的单词,以及一篇长为m的文章. 请问,有多少个单词在文章中出现了. #include<bits/stdc++.h> using namespace ...

  6. Flask(7)- request 对象

    Flask 中很重要的 request 对象 浏览器访问服务端时,向服务端发送请求 Flask 程序使用 request 对象描述请求信息 当你想获取请求体.请求参数.请求头数据的时候,就需要靠 re ...

  7. SpringCloud:Eureka注册中心设置显示IP路径

    未设置下的Eureka平台 可以看到Status显示的是 计算机名称! 解决方法: 在每一个需要注册的服务配置内加上如下几行配置 instance: prefer-ip-address: true # ...

  8. MySQL索引类型总结和使用技巧以及注意事项 (转)

      在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表:  代码如下: CREATE TABLE mytable(   ID INT NOT NULL,    us ...

  9. Java实验项目三——采用面向对象的方式设计线性表

    Program: 采用面向对象的方法设计一个线性表,目的是为其他需要用线性表的应用提供线性表对象. 1.list包中,定义线性表类 1 /* 2 * Description:定义线性表类 3 * 4 ...

  10. XCTF crypto 不仅仅是Mors

    一. 题目暗示摩斯码,打开文件发现里面有反斜杠的.不管它直接拿来解密 二. 发现一句话是句英文,还有其他的加密方式,后面那串只有两种字符A和B,手抓饼A套餐,b套餐 培根加密,拿来解密后,得到flag