ACSX: Aug, 2022
作者:互联网
8.1
T2数据水,只判4条边界就可以85pts,随机化2e5个非整点判断可以AC。
T2:
正解是扫描线,但是没人写。
T1 wisdom
我们采用一种贪心,假设当前已经处理完 u 的所有儿子子树,考虑把 u 染成什么颜色最优
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
inline int read(){
register char ch=getchar();register int x=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
const int N=2e6+5;
int n,a[N];
vector<int>f[N],G[N];
int dfs(int x){
if(a[x]){f[x].emplace_back(a[x]);return 1;}
int ret=0,mx=0;
unordered_map<int,int>mp;
for(int y:G[x]){
ret+=dfs(y);
for(int i:f[y]){
if(++mp[i]>mx)mx=mp[i],f[x].clear(),f[x].shrink_to_fit(),f[x].emplace_back(i);
else if(mp[i]==mx)f[x].emplace_back(i);
}
f[y].clear(),f[y].shrink_to_fit();
}
return ret-mx+1;
}
int main(){
freopen("wisdom.in","r",stdin);freopen("wisdom.out","w",stdout);
n=read();
for(int i=2,fa;i<=n;i++)fa=read(),G[fa].emplace_back(i);
for(int i=1;i<=n;i++)a[i]=read();
cout<<dfs(1);
}
8.2
T1 reward
“恰好”二字清晰提示了 wqs 二分,照常注意细节。
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
register char ch=getchar();register int x=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
typedef long long ll;
const int N=2e6+5;
int n,m,k,a[N],b[N],f[N],g[N],sum,ans;
int calc(int mid){
for(int i=1;i<=n;i++)b[i]=a[i]+mid;
f[0]=g[0]=0;
for(int i=1;i<=n;i++){
if(f[max(i-m,0ll)]+b[i]>=f[i-1])f[i]=f[max(i-m,0ll)]+b[i],g[i]=g[max(i-m,0ll)]+1;//>=
else f[i]=f[i-1],g[i]=g[i-1];
}
return g[n];
}
signed main(){
freopen("reward.in","r",stdin);freopen("reward.out","w",stdout);
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++)a[i]=read();
int L=-2e9,R=2e9,mid;
while(L<R-1){
mid=(L+R)/2;
int t=calc(mid);
if(t>=k)R=mid;
else L=mid;
}
int t=calc(R);
cout<<f[n]-R*k<<'\n';
}
T2 冬之花
容易想到这是可以平面图转对偶图跑最短路的。但是我有两点问题:①没有把对偶图形态画出来观察②没学过ddp
把对偶图形态画出来就会发现:
那么左边的两个线头可以看成一个起始点,显然可以 dp:
\(f[i][0]=min(f[i-1][0]+a[i],f[i-1][1]+c[i-1]+a[i])\)
\(f[i][1]=min(f[i-1][1]+b[i],f[i-1][0]+c[i-1]+b[i])\)
有经验的选手很容易看到“修改边权”就联想到动态 dp,再一看 [0][1] 就是板子题了。
|o[i-1][0] o[i-1][1]|×|a[i] c[i-1]+b[i]|
|c[i-1]+a[i] b[i]|
线段树维护区间积即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//o[i][0]=min(o[i-1][0]+a[i],o[i-1][1]+c[i-1]+a[i])
//o[i][1]=min(o[i-1][1]+b[i],o[i-1][0]+c[i-1]+b[i])
//|o[i-1][0] o[i-1][1]|*|a[i] c[i-1]+b[i]|
// |c[i-1]+a[i] b[i]|
inline int read(){
register char ch=getchar();register int x=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
void print(ll x){
if(x/10)print(x/10);
putchar(x%10+48);
}
const int N=5e5+5;
struct Mat1 {ll o[2];Mat1(){o[0]=o[1]=0;}}tmp;
struct Mat2 {ll o[2][2];Mat2(){o[0][0]=o[0][1]=o[1][0]=o[1][1]=0;}}t[N<<2];
int n,q,a[N],b[N],c[N];
Mat1 operator*(Mat1 a,Mat2 b){
Mat1 c;
c.o[0]=min(a.o[0]+b.o[0][0],a.o[1]+b.o[1][0]);
c.o[1]=min(a.o[0]+b.o[0][1],a.o[1]+b.o[1][1]);
return c;
}
Mat2 operator*(Mat2 a,Mat2 b){
Mat2 c;
c.o[0][0]=min(a.o[0][0]+b.o[0][0],a.o[0][1]+b.o[1][0]);
c.o[0][1]=min(a.o[0][0]+b.o[0][1],a.o[0][1]+b.o[1][1]);
c.o[1][0]=min(a.o[1][0]+b.o[0][0],a.o[1][1]+b.o[1][0]);
c.o[1][1]=min(a.o[1][0]+b.o[0][1],a.o[1][1]+b.o[1][1]);
return c;
}
void pushup(int k){t[k]=t[k<<1]*t[k<<1|1];}
void build(int l,int r,int k){
if(l==r){
t[k].o[0][0]=a[l],t[k].o[0][1]=c[l]+b[l],t[k].o[1][0]=c[l]+a[l];t[k].o[1][1]=b[l];
return;
}
int mid=l+r>>1;
build(l,mid,k<<1),build(mid+1,r,k<<1|1);
pushup(k);
}
void chg(int type,int p,int l,int r,int k){
if(l==r){
if(type==1)t[k].o[0][0]=a[p],t[k].o[1][0]=c[p]+a[p];
if(type==2)t[k].o[0][1]=c[p]+b[p],t[k].o[1][1]=b[p];
if(type==3)t[k].o[0][1]=c[p]+b[p],t[k].o[1][0]=c[p]+a[p];
return;
}
int mid=l+r>>1;
if(p<=mid)chg(type,p,l,mid,k<<1);
else chg(type,p,mid+1,r,k<<1|1);
pushup(k);
}
Mat2 ask(int L,int R,int l,int r,int k){
if(L<=l&&r<=R)return t[k];
int mid=l+r>>1;
if(L<=mid&&R>mid)return ask(L,R,l,mid,k<<1)*ask(L,R,mid+1,r,k<<1|1);
if(L<=mid)return ask(L,R,l,mid,k<<1);
return ask(L,R,mid+1,r,k<<1|1);
}
int main(){
freopen("hana.in","r",stdin);freopen("hana.out","w",stdout);
n=read(),q=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=2;i<=n;i++)c[i]=read();
build(1,n,1);
for(int op,l,r;q--;){
op=read(),l=read(),r=read();
if(op==1)a[l]=r,chg(1,l,1,n,1);
if(op==2)b[l]=r,chg(2,l,1,n,1);
if(op==3)c[l+1]=r,chg(3,l+1,1,n,1);
if(op==4){
tmp.o[0]=tmp.o[1]=0,tmp=tmp*ask(l,r,1,n,1),print(min(tmp.o[0],tmp.o[1])),puts("");
}
}
}
标签:ch,ACSX,Aug,int,register,read,while,2022,getchar 来源: https://www.cnblogs.com/impyl/p/16544824.html