noip模擬測試34
這次考試,全靠第一題撐著了,第一題我畫了畫圖,就看出了二分答案,然後差不多半個小時就碼的差不多了,又加上了一點小優化,但是沒拿到滿分,失誤有兩點,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;
}