这次考试,全靠第一题撑着了,第一题我画了画图,就看出了二分答案,然后差不多半个小时就码的差不多了,又加上了一点小优化,但是没拿到满分,失误有两点,1.二分之前没有特判0的情况 2.这属于一个知识性问题,我当时不知道,因为快排带log,所以我们可以使用一个 nth_element()取出序列前m大。然后是T2,虽然题面看起来像是一个高斯消元,但是结合数据范围,我就知道事情没有辣么简单,高斯消元一次就是n^3, 显然过不去,但是,我当时注意到了每次之需要求出 x1,但是没想到把所有变量都用 x1 表示(我太菜了),最后是T3,我当时一直在想一条直线扫过来扫过去,但是我不知道如何实现,想了半天只能打个暴力,还打假了。这次要没有T1,估计又要保龄了。。。
T1 Merchant
思路:画个图,因为每个物品的价值都是一个一次函数,所以显然具有决策单调性,我们可以进行二分答案,但是由于我们需要取出序列前m大,可以使用nth_element() O(N),求出,但是,这东西只能保证将序列前 m 小的东西放在前 m 位,但不保证是有序的,所以在计算过程中我们需要特判,如果小于0就选择不放。
代码如下:
AC_code
#include<bits/stdc++.h>
#define int long long
#define re register int
#define ii inline int
#define iv inline void
using namespace std;
const int N=1e6+10;
struct node
{
int k,b;
}use[N];
int n,m,s;
ii read()
{
int x=0;
bool f=1;
char ch=getchar();
while(ch<‘0‘||ch>‘9‘)
{
if(ch==‘-‘)
f=0;
ch=getchar();
}
while(ch>=‘0‘&&ch<=‘9‘)
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f?x:(-x);
}
inline bool check(int x)
{
int cnt=0,sum=0;
int q[N];
for(re i=1;i<=n;i++)
q[i]=((use[i].k*x+use[i].b)*-1);
nth_element(q+1,q+m+1,q+n+1);
for(re i=1;i<=m;i++)
{
if(sum>=s)
break;
if(q[i]<0)
sum-=q[i];
}
return sum>=s;
}
ii my(node a,node b)
{
if(a.k!=b.k)
return a.k>b.k;
return a.b>b.b;
}
signed main()
{
n=read();
m=read();
s=read();
bool fu=1,zh=1;
for(re i=1;i<=n;i++)
{
use[i].k=read();
use[i].b=read();
if(use[i].k>0)
fu=0;
if(use[i].k<0)
zh=0;
}
sort(use+1,use+n+1,my);
if(check(0))
{
printf("0\n");
return 0;
}
int l=0,r=1e9+10,out=r,out2=r;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
out=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("%lld\n",out);
return 0;
}
T2 Equation
思路:看到这种数据范围,显然是nlogn,所以我们考虑使用线段树,显然,我们可以将每个变量表示成 \(x_i=k_i+x_1\) 或 \(x_i=k_i-x_1\) 的形式,那么对于询问 u,v,t ,将表示 u 和 v的式子加起来,只会存在如下几种情况,
1.\(x_u+x_v=t\),只需要判断等式是否成立.
2.\(x_u+x_v=t-2\times x_1\)
3.\(x_u+x_v=t+2\times x_1\)
那么这就是一个区间修改,单点查询的操作,我们可以使用线段树或者树状数组实现,我使用了线段树,我们在线段树上只需要保存三个东西,自己的权值(sum),两个延迟标记(lazy),由于修改的时候对于深度为奇偶的点影响不同,所以这两个延迟标记数组一个是奇加偶减,另一个是偶加奇减,还要注意在每次 change 的时候都要判断当前的深度奇偶性!!
代码如下:
AC_code
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
#define lc (rt<<1)
#define rc (rt<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int N=1e6+10;
int n,q,tot,timi;
int to[N<<1],next[N<<1],val[N<<1],head[N];
int size[N],deep[N],id[N],dp[N],zh[N],ifs[N],fw[N];
ii read()
{
int x=0;
bool f=1;
char ch=getchar();
while(ch<‘0‘||ch>‘9‘)
{
if(ch==‘-‘)
f=0;
ch=getchar();
}
while(ch>=‘0‘&&ch<=‘9‘)
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f?x:(-x);
}
struct Segment_Tree
{
int sum[N<<2],lazy1[N<<2],lazy2[N<<2];
iv updata_1(int p,int l,int r,int w)
{
if(l==r)
{
if(deep[ifs[l]])
sum[p]+=w;
else
sum[p]-=w;
return;
}
lazy1[p]+=w;
}
iv updata_2(int p,int l,int r,int w)
{
if(l==r)
{
if(deep[ifs[l]])
sum[p]-=w;
else
sum[p]+=w;
return;
}
lazy2[p]+=w;
}
iv pd(int rt,int l,int r)
{
if(lazy1[rt])
{
updata_1(lc,l,mid,lazy1[rt]);
updata_1(rc,mid+1,r,lazy1[rt]);
lazy1[rt]=0;
}
if(lazy2[rt])
{
updata_2(lc,l,mid,lazy2[rt]);
updata_2(rc,mid+1,r,lazy2[rt]);
lazy2[rt]=0;
}
}
iv build(int rt,int l,int r)
{
if(l==r)
{
sum[rt]=zh[l];
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
}
inline long long query(int rt,int l,int r,int p)
{
if(l==r)
return sum[rt];
pd(rt,l,r);
if(mid>=p)
return query(lc,l,mid,p);
return query(rc,mid+1,r,p);
}
iv insert_1(int rt,int l,int r,int L,int R,int z)
{
if(L>R)
return;
if(L<=l&&r<=R)
{
if(l==r)
{
if(deep[ifs[l]])
sum[rt]+=z;
else
sum[rt]-=z;
return;
}
lazy1[rt]+=z;
return;
}
pd(rt,l,r);
if(mid>=L)
insert_1(lc,l,mid,L,R,z);
if(mid<R)
insert_1(rc,mid+1,r,L,R,z);
}
iv insert_2(int rt,int l,int r,int L,int R,int z)
{
if(L>R)
return;
if(L<=l&&r<=R)
{
if(l==r)
{
if(deep[ifs[l]])
sum[rt]-=z;
else
sum[rt]+=z;
return;
}
lazy2[rt]+=z;
return;
}
pd(rt,l,r);
if(mid>=L)
insert_2(lc,l,mid,L,R,z);
if(mid<R)
insert_2(rc,mid+1,r,L,R,z);
}
}T;
iv add(int x,int y,int w)
{
to[++tot]=y;
next[tot]=head[x];
head[x]=tot;
val[tot]=w;
}
iv dfs(int st,int f)
{
deep[st]=deep[f]^1;
size[st]=1;
id[st]=++timi;
ifs[timi]=st;
for(re i=head[st];i;i=next[i])
{
int p=to[i];
dfs(p,st);
size[st]+=size[p];
}
}
iv dfs2(int st,int f)
{
for(re i=head[st];i;i=next[i])
{
int p=to[i];
zh[id[p]]=val[i]-zh[id[st]];
dfs2(p,st);
}
}
signed main()
{
n=read();
q=read();
int f,w,opt,u,v;
long long ans1,ans2,s;
for(re i=2;i<=n;i++)
{
f=read();
w=read();
fw[i]=w;
add(f,i,w);
}
dfs(1,0);
dfs2(1,0);
T.build(1,1,n);
while(q--)
{
opt=read();
if(opt==1)
{
u=read();
v=read();
s=read();
ans1=T.query(1,1,n,id[u]);
ans2=T.query(1,1,n,id[v]);;
if(deep[u]!=deep[v])
{
if(ans1+ans2!=s)
printf("none\n");
else
printf("inf\n");
}
else
{
if(deep[u]==0)
{
if(!((ans1+ans2-s)&1))
printf("%d\n",(ans1+ans2-s)/2);
else
printf("none\n");
}
else
{
if(!((s-ans1-ans2)&1))
printf("%d\n",(s-ans1-ans2)/2);
else
printf("none\n");
}
}
}
else
{
u=read();
w=read();
int tmp=w;
w=w-fw[u];
if(deep[u])
T.insert_1(1,1,n,id[u],id[u]+size[u]-1,w);
else
T.insert_2(1,1,n,id[u],id[u]+size[u]-1,w);
fw[u]=tmp;
}
}
return 0;
}