其他分享
首页 > 其他分享> > ACSX: Aug, 2022

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