zoukankan      html  css  js  c++  java
  • 省选测试42

    省选测试42

    总结

    这次是真的掉没了,(T1) 加了一个剪枝直接把 (60) 分减没了,以后遇到这种情况还是要稳一点,不要把暴力留着,尤其是这种数据不是很好构造的题。

    A. 小B的棋盘

    分析

    将所有的点按照横坐标从小到大排序,如果横坐标相同按照纵坐标从小到大排序。

    如果我们确定了一个对称中心,那么判断方法就是维护两个指针,一个从前向后扫,一个从后向前扫,求出有多少对点匹配,也就可以求出我们需要加入多少点。

    因为我们最多只能加入 (k) 个点,所以失配的次数不能超过 (k) 次。

    因此就可以把最开始的 (k+1) 个点和最后的 (k+1) 个点选择一对强制匹配,最终的合法方案一定是在这些方案中的。

    判断的时候可以 (nlogn) 判断,总的复杂度就是 (k^2nlogn)

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1e5+5;
    int n,k,x[maxn],y[maxn],ans,tp;
    struct Node{
    	long long x,y;
    	Node(){}
    	Node(rg long long aa,rg long long bb){
    		x=aa,y=bb;
    	}
    	friend bool operator <(const Node& A,const Node& B){
    		if(A.x==B.x) return A.y<B.y;
    		return A.x<B.x;
    	}
    }sta[maxn];
    std::set<Node> s,mp,orz;
    #define sit std::set<Node>::iterator
    bool jud(rg long long nx,rg long long ny){
    	rg sit it=mp.find(Node(nx,ny));
    	if(it!=mp.end() && it->x==nx && it->y==ny) return 0;
    	rg int cnt=0;
    	rg long long mx,my;
    	for(rg int i=1;i<=n;i++){
    		mx=2LL*nx-x[i];
    		my=2LL*ny-y[i];
    		it=s.find(Node(mx,my));
    		if(it==s.end() || it->x!=mx || it->y!=my) cnt++;
    		if(cnt>k) return 0;
    	}
    	mp.insert(Node(nx,ny));
    	return 1;
    }
    int main(){
    	read(n),read(k);
    	for(rg int i=1;i<=n;i++){
    		read(x[i]),read(y[i]);
    		x[i]*=2,y[i]*=2;
    		s.insert(Node(x[i],y[i]));
    		sta[++tp]=Node(x[i],y[i]);
    	}
    	if(k>=n){
    		printf("-1
    ");
    		return 0;
    	}
    	std::sort(sta+1,sta+tp+1);
    	for(rg int i=1;i<=k+1;i++){
    		for(rg int j=tp-k;j<=tp;j++){
    			ans+=jud(1LL*(sta[i].x+sta[j].x)/2LL,1LL*(sta[i].y+sta[j].y)/2LL);
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    B. 小B的夏令营

    分析

    (f[t][l][r]) 为当前考虑到了第 (t) 行,前 (i) 行都联通并且剩下的区间是 ([l,r]) 的概率。

    暴力的转移是 (n^5) 的,拿前缀和优化一下就是 (n^3) 的。

    发现其实并不需要维护具体的 (f) 值,只需要维护前缀和的值就行了,拆一下式子就可以做到 (n^2)

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1505,mod=1e9+7,maxm=1e5+5;
    inline int addmod(rg int now1,rg int now2){
    	return now1+=now2,now1>=mod?now1-mod:now1;
    }
    inline int delmod(rg int now1,rg int now2){
    	return now1-=now2,now1<0?now1+mod:now1;
    }
    inline int mulmod(rg long long now1,rg int now2){
    	return now1*=now2,now1>=mod?now1%mod:now1;
    }
    inline int ksm(rg int ds,rg int zs){
    	rg int nans=1;
    	while(zs){
    		if(zs&1) nans=mulmod(nans,ds);
    		ds=mulmod(ds,ds);
    		zs>>=1;
    	}
    	return nans;
    }
    int n,m,a,b,k,ans,p[maxn],ny[maxm],jc[maxm],jcc[maxm],gl;
    int suml[2][maxn],sumr[2][maxn],suml2[maxn],sumr2[maxn],suml3[maxn],sumr3[maxn],sumpl[maxn],sumpr[maxn];
    int getp(rg int l,rg int r){
    	return mulmod(p[l-1],p[m-r]);
    }
    int getC(rg int nn,rg int mm){
    	return mulmod(jc[nn],mulmod(jcc[nn-mm],jcc[mm]));
    }
    int main(){
    	read(n),read(m),read(a),read(b),read(k);
    	gl=mulmod(a,ksm(b,mod-2));
    	ny[1]=1;
    	for(rg int i=2;i<maxm;i++) ny[i]=mulmod(mod-mod/i,ny[mod%i]);
    	jc[0]=jcc[0]=1;
    	for(rg int i=1;i<maxm;i++) jc[i]=mulmod(jc[i-1],i),jcc[i]=mulmod(jcc[i-1],ny[i]);
    	for(rg int i=0;i<=m && i<=k;i++) p[i]=mulmod(getC(k,i),mulmod(ksm(gl,i),ksm(delmod(1,gl),k-i)));
    	for(rg int i=1;i<=m;i++){
    		for(rg int j=1;j<=i;j++){
    			sumpr[i]=addmod(sumpr[i],getp(j,i));
    		}
    	}
    	for(rg int i=1;i<=m;i++){
    		for(rg int j=i;j<=m;j++){
    			sumpl[i]=addmod(sumpl[i],getp(i,j));
    		}
    	}
    	rg int now=0;
    	sumr[now][m]=1,suml[now][1]=1;
    	for(rg int o=1;o<=n;o++){
    		memset(suml2,0,sizeof(suml2));
    		memset(sumr2,0,sizeof(sumr2));
    		memset(suml3,0,sizeof(suml3));
    		memset(sumr3,0,sizeof(sumr3));
    		for(rg int i=1;i<=m;i++) sumr2[i]=addmod(sumr2[i-1],sumr[now][i]);
    		for(rg int i=m;i>=1;i--) suml2[i]=addmod(suml2[i+1],suml[now][i]);
    		for(rg int i=1;i<=m;i++) sumr3[i]=addmod(sumr3[i-1],mulmod(p[i-1],sumr2[i-1]));
    		for(rg int i=m;i>=1;i--) suml3[i]=addmod(suml3[i+1],mulmod(p[m-i],suml2[i+1]));
    		now^=1;
    		memset(suml[now],0,sizeof(suml[now]));
    		memset(sumr[now],0,sizeof(sumr[now]));
    		for(rg int i=1;i<=m;i++){
    			sumr[now][i]=addmod(sumr[now][i],mulmod(sumr2[m],sumpr[i]));
    			sumr[now][i]=delmod(sumr[now][i],mulmod(suml2[i+1],sumpr[i]));
    			sumr[now][i]=delmod(sumr[now][i],mulmod(p[m-i],sumr3[i]));
    		}
    		for(rg int i=1;i<=m;i++){
    			suml[now][i]=addmod(suml[now][i],mulmod(sumr2[m],sumpl[i]));
    			suml[now][i]=delmod(suml[now][i],mulmod(sumr2[i-1],sumpl[i]));
    			suml[now][i]=delmod(suml[now][i],mulmod(p[i-1],suml3[i]));
    		}
    	}
    	for(rg int i=1;i<=m;i++) ans=addmod(ans,sumr[now][i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    C. 小B的图

    分析

    首先,不管什么 (x),选出的边一定要么是 (A) 的最小生成树边,要么是 (B) 的最小生成树边。

    我们搞出 (A) 的最小生成树,把 (B) 的边从小到大依次加入替代 (A) 边。

    每条边替换时我们能知道这条边在 $ ge x_0$ 时才会被替换。

    排个序然后每次询问二分就行。

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #define rg register
    template<typename T>void read(rg T& x){
    	x=0;rg int fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	x*=fh;
    }
    const int maxn=1e6+5;
    struct LCT{
    	int rev[maxn],wz[maxn],val[maxn],mmax[maxn],ch[maxn][2],fa[maxn],sta[maxn],tp;
    	void push_up(rg int da){
    		rg int lc=ch[da][0],rc=ch[da][1];
    		mmax[da]=std::max(val[da],std::max(mmax[lc],mmax[rc]));
    		if(mmax[da]==val[da]) wz[da]=da;
    		else if(mmax[da]==mmax[lc]) wz[da]=wz[lc];
    		else wz[da]=wz[rc];
    	}
    	void push_down(rg int da){
    		if(!rev[da]) return;
    		rg int lc=ch[da][0],rc=ch[da][1];
    		rev[da]^=1,rev[lc]^=1,rev[rc]^=1;
    		std::swap(ch[da][0],ch[da][1]);
    	}
    	bool isroot(rg int da){
    		return (ch[fa[da]][0]!=da)&&(ch[fa[da]][1]!=da);
    	}
    	void xuanzh(rg int x){
    		rg int y=fa[x];
    		rg int z=fa[y];
    		rg int k=(ch[y][1]==x);
    		if(!isroot(y)) ch[z][ch[z][1]==y]=x;
    		fa[x]=z;
    		ch[y][k]=ch[x][k^1];
    		fa[ch[x][k^1]]=y;
    		ch[x][k^1]=y;
    		fa[y]=x;
    		push_up(y);
    		push_up(x);
    	}
    	void splay(rg int x){
    		sta[tp=1]=x;
    		for(rg int i=x;!isroot(i);i=fa[i]) sta[++tp]=fa[i];
    		for(rg int i=tp;i>=1;i--) push_down(sta[i]);
    		while(!isroot(x)){
    			rg int y=fa[x];
    			rg int z=fa[y];
    			if(!isroot(y)){
    				(ch[z][1]==y)^(ch[y][1]==x)?xuanzh(x):xuanzh(y);
    			}
    			xuanzh(x);
    		}
    	}
    	void access(rg int x){
    		for(rg int y=0;x;y=x,x=fa[x]){
    			splay(x);
    			ch[x][1]=y;
    			push_up(x);
    		}
    	}
    	void makeroot(rg int x){
    		access(x);
    		splay(x);
    		rev[x]^=1;
    		push_down(x);
    	}
    	void split(rg int x,rg int y){
    		makeroot(x);
    		access(y);
    		splay(y);
    	}
    	void link(rg int x,rg int y){
    		makeroot(x);
    		fa[x]=y;
    	}
    	void cut(rg int x,rg int y){
    		split(x,y);
    		ch[y][0]=fa[x]=0;
    		push_up(y);
    	}
    }lct;
    int n,a,b,q,fa[maxn],idx[maxn],idy[maxn],idw[maxn],tp,wz[maxn];
    struct jie{
    	int zb,yb,val;
    	jie(){}
    	jie(rg int aa,rg int bb,rg int cc){
    		zb=aa,yb=bb,val=cc;
    	}
    }c[maxn];
    bool cmp(rg jie aa,rg jie bb){
    	return aa.val<bb.val;
    }
    void init(){
    	for(rg int i=1;i<=n;i++) fa[i]=i;
    }
    int zhao(rg int xx){
    	if(xx==fa[xx]) return xx;
    	return fa[xx]=zhao(fa[xx]);
    }
    long long ans[maxn];
    struct asd{
    	int val,tim;
    	asd(){}
    	asd(rg int aa,rg int bb){
    		val=aa,tim=bb;
    	}
    }sta[maxn];
    bool cmp2(rg asd aa,rg asd bb){
    	return aa.tim<bb.tim;
    }
    int main(){
    	read(n),read(a),read(b),read(q);
    	for(rg int i=0;i<=n;i++) lct.val[i]=lct.mmax[i]=-0x3f3f3f3f;
    	rg int aa,bb,cc;
    	for(rg int i=1;i<=a;i++){
    		read(aa),read(bb),read(cc);
    		c[i]=jie(aa,bb,cc);
    	}
    	std::sort(c+1,c+a+1,cmp);
    	init();
    	for(rg int i=1;i<=a;i++){
    		aa=zhao(c[i].zb),bb=zhao(c[i].yb);
    		if(aa==bb) continue;
    		fa[aa]=bb;
    		lct.val[i+n]=lct.mmax[i+n]=c[i].val;
    		idx[i+n]=c[i].zb,idy[i+n]=c[i].yb,idw[i+n]=c[i].val;
    		lct.link(c[i].zb,i+n),lct.link(c[i].yb,i+n);
    		ans[0]+=c[i].val;
    	}
    	for(rg int i=1;i<=b;i++){
    		read(aa),read(bb),read(cc);
    		c[i]=jie(aa,bb,cc);
    	}
    	std::sort(c+1,c+b+1,cmp);
    	init();
    	for(rg int i=1;i<=b;i++){
    		aa=zhao(c[i].zb),bb=zhao(c[i].yb);
    		if(aa==bb) continue;
    		fa[aa]=bb;
    		lct.split(c[i].zb,c[i].yb);
    		cc=lct.wz[c[i].yb];
    		lct.cut(idx[cc],cc),lct.cut(idy[cc],cc);
    		lct.val[n+a+i]=lct.mmax[n+a+i]=-0x3f3f3f3f;
    		lct.link(c[i].zb,n+a+i),lct.link(c[i].yb,n+a+i);
    		sta[++tp]=asd(c[i].val-idw[cc],(int)std::ceil(1.0*(c[i].val-idw[cc])/2.0));
    	}
    	std::sort(sta+1,sta+tp+1,cmp2);
    	for(rg int i=1;i<=tp;i++) ans[i]=ans[i-1]+sta[i].val;
    	for(rg int i=1;i<=tp;i++) wz[i]=sta[i].tim;
    	for(rg int i=1;i<=q;i++){
    		read(aa);
    		if(aa>=sta[tp].tim){
    			printf("%lld
    ",ans[tp]-1LL*(n-1)*aa);
    		} else {
    			bb=std::upper_bound(wz+1,wz+tp+1,aa)-wz;
    			printf("%lld
    ",ans[bb-1]+1LL*(n-1-(bb-1)-(bb-1))*aa);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    为什么使用C#开发软件的公司和程序员都很少?
    使用Redis之前5个必须了解的事情
    这段代码为什么捕获不到异常呢?谁能给个解释,谢谢。
    git报错
    C# 常用类库(字符串处理,汉字首字母拼音,注入攻击,缓存操作,Cookies操作,AES加密等)
    你所不知道的 CSS 负值技巧与细节
    CSS 属性选择器的深入挖掘
    探秘 flex 上下文中神奇的自动 margin
    CSS 火焰?不在话下
    不可思议的纯 CSS 实现鼠标跟随效果
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14578954.html
Copyright © 2011-2022 走看看