2021.8.8考試總結[NOIP模擬33]
阿新 • • 發佈:2021-08-08
T1Hunter T2Defence T3Connect
T1 Hunter
考場上一看期望直接狀壓拿了$45pts$跑了。結果正解只用$4$行?
把問題轉化為一號獵人之前死的獵人數的期望加一。
期望的線性性。
對每個獵人$i$,$w_i+w_1$種情況中有$w_i$種死於一號獵人之前,故期望為$\frac{w_i}{w_i+w_1}$。
列舉累加即可。
$code:$
1 #include<bits/stdc++.h> 2 #define rin register signed 3 #define int long long 4 using namespace std; 5 const int NN=1e5+5,p=998244353T1; 6 int n,w[NN],f[1<<20],inv[1<<20],iv[NN],ans; 7 inline int read(){ 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 10 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 11 return x*f;12 } 13 inline void write(int x){ 14 char ch[20]; int len=0; 15 if(x<0) putchar('-'), x=~x+1; 16 do{ 17 ch[len++]=x%10+(1<<5)+(1<<4); 18 x/=10; 19 }while(x); 20 for(rin i=len-1;i>=0;--i) putchar(ch[i]); 21 return; 22 } 23 inline int qpow(int a,int b){24 int res=1; 25 while(b){ 26 if(b&1) res=res*a%p; 27 a=a*a%p; 28 b>>=1; 29 } 30 return res; 31 } 32 signed main(){ 33 n=read(); f[0]=1; 34 for(int i=1;i<=n;i++) w[i]=read(), iv[i]=qpow(w[i],p-2); 35 for(int i=2;i<=n;i++) 36 (ans+=w[i]*qpow(w[1]+w[i],p-2)%p)%=p; 37 write(ans+1); putchar('\n'); 38 return 0; 39 }
T2 Defence
不難想到最優策略是先用法術再用符咒,而最後答案是字首零,字尾零的和與區間中最長零串取$min$。動態開點線段樹向上合併即可。
以上思路是考場看題$10min$後出的。然後線段樹假上加假,$WA+MLE$掉成樣例分。。
線段樹合併太長時間不打了,細節不清,答案在最後統一記導致合併時只能新開節點。
玫瑰花精的印象不深,原來打過一樣的$pushup$,要特判兒子是否為空,但這次又忘了。這算掛$91pts$嗎?
$code:$
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int NN=1e5+5; 4 int n,m,q,to[NN<<1],nex[NN<<1],head[NN<<1],num,ans[NN]; 5 inline int read(){ 6 int x=0,f=1; char ch=getchar(); 7 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 8 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 9 return x*f; 10 } 11 inline void write(int x){ 12 char ch[20]; int len=0; 13 if(x<0) putchar('-'), x=~x+1; 14 do{ 15 ch[len++]=x%10+(1<<5)+(1<<4); 16 x/=10; 17 }while(x); 18 for(int i=len-1;i>=0;--i) putchar(ch[i]); 19 return; 20 } 21 inline void add(int a,int b){ 22 to[++num]=b; nex[num]=head[a]; head[a]=num; 23 to[++num]=a; nex[num]=head[b]; head[b]=num; 24 } 25 struct segment_tree{ 26 int tot,root[NN],mx[NN*40],lc[NN*40],rc[NN*40],lz[NN*40],rz[NN*40]; 27 void pushup(int rt){ 28 if(!lz[lc[rt]]){ lz[rt]=lz[rc[rt]]; rz[rt]=rz[rc[rt]]; mx[rt]=mx[rc[rt]]; return; } 29 if(!lz[rc[rt]]){ lz[rt]=lz[lc[rt]]; rz[rt]=rz[lc[rt]]; mx[rt]=mx[lc[rt]]; return; } 30 int tmp=lz[rc[rt]]-rz[lc[rt]]-1; 31 mx[rt]=max(max(mx[lc[rt]],mx[rc[rt]]),tmp); 32 lz[rt]=lz[lc[rt]]?lz[lc[rt]]:lz[rc[rt]]; 33 rz[rt]=rz[rc[rt]]?rz[rc[rt]]:rz[lc[rt]]; 34 } 35 void update(int &rt,int l,int r,int pos){ 36 if(!rt) rt=++tot; 37 if(l==r){ lz[rt]=rz[rt]=l; return; } 38 int mid=l+r>>1; 39 if(pos<=mid) update(lc[rt],l,mid,pos); 40 else update(rc[rt],mid+1,r,pos); 41 pushup(rt); 42 } 43 void merge(int &rt,int oth,int l,int r){ 44 if(!rt){ rt=oth; return; } 45 if(l==r){ 46 if(lz[oth]){ 47 mx[rt]=0; 48 lz[rt]=rz[rt]=l; 49 } 50 return; 51 } 52 int mid=l+r>>1; 53 if(lz[lc[oth]]) merge(lc[rt],lc[oth],l,mid); 54 if(rz[rc[oth]]) merge(rc[rt],rc[oth],mid+1,r); 55 pushup(rt); 56 } 57 }s; 58 void dfs(int f,int st){ 59 for(int i=head[st];i;i=nex[i]){ 60 int v=to[i]; 61 if(v==f) continue; 62 dfs(st,v); 63 s.merge(s.root[st],s.root[v],1,m); 64 } 65 int now=s.root[st]; 66 if(!s.lz[now])ans[st]=-1; 67 else ans[st]=max(s.mx[now],m+s.lz[now]-1-s.rz[now]); 68 } 69 signed main(){ 70 n=read(); m=read(); q=read(); 71 for(int i=1;i<n;i++) add(read(),read()); 72 for(int i=1;i<=q;i++){ 73 int u=read(),v=read(); 74 s.update(s.root[u],1,m,v); 75 } 76 dfs(0,1); 77 for(int i=1;i<=n;i++) 78 write(ans[i]), putchar('\n'); 79 return 0; 80 }T2
T3 Connect
狀壓全是神仙題。
題意稍微轉化一下,不在$1\rightborrow n$