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

    A. 倚天剑的愤怒

    分析

    (15) 分的做法是从前往后扫,遇到不合法的时候就从前面找一个最小的减掉

    正解需要倒着考虑

    维护一个 (multiset)

    如果遇到一个负数直接扔到 (multiset)

    如果遇到一个正数,那么我们肯定想让它抵消掉尽可能多的负数,直到它变成零

    最后把剩下的负数做一个前缀和,二分查找即可

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<set>
    #define rg register
    const int maxn=1e6+5;
    int n,m,a[maxn],cnt,tp;
    long long beg,sum[maxn];
    std::multiset<int> s;
    #define sit std::multiset<int>::iterator
    int main(){
    	scanf("%d%d",&n,&m);
    	for(rg int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(rg int i=n;i>=1;i--){
            if(a[i]<0) s.insert(-a[i]);
            else {
                while(!s.empty()){
                    rg int tmp=*s.begin();
                    s.erase(s.begin());
                    if(a[i]>=tmp) a[i]-=tmp;
                    else {
                        s.insert(tmp-a[i]);
                        break;
                    }
                }
            }
        }
        for(rg sit it=s.begin();it!=s.end();++it) sum[++tp]=*it;
        for(rg int i=1;i<=tp;i++) sum[i]+=sum[i-1];
    	for(rg int i=1;i<=m;i++){
    		scanf("%lld",&beg);
            if(beg>=sum[tp]) cnt=0;
            else cnt=tp-(std::upper_bound(sum+1,sum+1+tp,beg)-sum)+1;
    		printf("%d
    ",cnt);
    	}
    	return 0;
    }
    

    B. 原谅

    分析

    考试的时候挂成了 (40)

    调了一下午+一晚上,拍了几千组没拍出错

    然后去 (51Nod) 上下载数据,手调 (10000) 个节点的树

    发现是删叶子节点的时候删挂了

    一条边我强制让权值小的连向权值大的,然后没考虑权值相等的

    这样在更新的时候就有可能更新不到

    这道题的思路还是比较简单的

    将点按照权值从大到小排序

    对于当前一个值 (x)

    先把权值大于等于 (x) 的加入并查集

    然后删权值等于 (x) 的叶子节点,能删多少删多少

    要求删完之后必须在一个联通块中并且联通块的大小小于等于 (k)

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<vector>
    #define rg register
    inline int read(){
    	rg int x=0,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();
    	}
    	return x*fh;
    }
    const int maxn=1e6+5;
    int n,m;
    struct asd{
    	int zb,yb;
    	asd(){}
    	asd(rg int aa,rg int bb){
    		zb=aa,yb=bb;
    	}
    }b[maxn];
    int du[maxn],a[maxn],id[maxn],ans,fa[maxn],cnt,vis[maxn],tim,siz[maxn],maxsiz=1;
    std::vector<int> g[maxn],g2[maxn];
    bool cmp(rg int aa,rg int bb){
    	return a[aa]>a[bb];
    }
    int sta[maxn],tp;
    int zhao(rg int xx){
    	if(xx==fa[xx]) return xx;
    	return fa[xx]=zhao(fa[xx]);
    }
    void bing(rg int xx,rg int yy){
    	xx=zhao(xx),yy=zhao(yy);
    	if(xx==yy) return;
    	fa[xx]=yy,siz[yy]+=siz[xx],siz[xx]=0;
    	maxsiz=std::max(maxsiz,siz[yy]);
    	cnt--;
    }
    std::queue<int> q;
    void updat(rg int now){
    	for(rg int j=0;j<g[now].size();j++){
    		rg int u=g[now][j];
    		du[u]++,du[now]++;
    	}
    	sta[++tp]=now;
    }
    int main(){
    	n=read(),m=read();
    	for(rg int i=1;i<=n;i++) a[i]=read(),fa[i]=i,siz[i]=1;
    	rg int aa,bb;
    	for(rg int i=1;i<n;i++){
    		aa=read()+1,bb=read()+1;
    		if(a[aa]>a[bb]) g[bb].push_back(aa);
    		else g[aa].push_back(bb);
    		if(a[aa]==a[bb]) g2[aa].push_back(bb),g2[bb].push_back(aa);
    	}
    	for(rg int i=1;i<=n;i++) id[i]=i;
    	std::sort(id+1,id+1+n,cmp);
    	rg int lat=1e9,tmp=0,haha=0;
    	for(rg int i=1;i<=n+1;i++){
    		rg int now=id[i];
    		if(a[now]==lat){
    			updat(now);
    			continue;
    		}
    		tim++,tmp=0,haha=0;
    		for(rg int j=1;j<=tp;j++){
    			if(du[sta[j]]<=1) q.push(sta[j]),vis[sta[j]]=tim,tmp++;
    		}
    		while(!q.empty()){
    			rg int tmp1=q.front();q.pop();
    			for(rg int j=0;j<g2[tmp1].size();j++){
    				rg int u=g2[tmp1][j];
    				if(vis[u]!=tim){
    					du[u]--;
    					if(du[u]==1){
    						vis[u]=tim,tmp++;
    						q.push(u);
    					}
    				}
    			}
    		}
    		for(rg int j=1;j<=tp;j++){
    			if(vis[sta[j]]==tim) continue;
    			for(rg int k=0;k<g[sta[j]].size();k++){
    				rg int u=g[sta[j]][k];
    				if(vis[u]==tim) continue;
    				bing(sta[j],u);
    			}
    		}
    		cnt+=tp-tmp;
    		if(maxsiz>m) break;
    		if(cnt<=1) ans=std::max(ans,maxsiz),haha=1;
    		for(rg int j=1;j<=tp;j++){
    			for(rg int k=0;k<g[sta[j]].size();k++){
    				rg int u=g[sta[j]][k];
    				bing(sta[j],u);
    			}
    		}
    		cnt+=tmp;
    		if(haha) ans=std::max(ans,std::min(m,siz[zhao(id[1])]));
    		if(tim==2) ans=std::max(ans,std::min(maxsiz,m));
    		if(ans==m) break;
    		lat=a[now],tp=0;
    		updat(now);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    C. 收集

    分析

    暑假集训的时候做过一个类似的题,然而没想起来

    有一个结论:(DFS) 序求出后,假设关键点按照 (DFS) 序排序后是 ({a_1,a_2,ldots ,a_k})

    那么所有关键点形成的极小连通子树的边权和的两倍等于 (mathrm{dist}(a_1,a_2)+mathrm{dist}(a_2,a_3)+cdots+mathrm{dist}(a_{k-1},a_k)+mathrm{dist}(a_k,a_1))

    所以遇到一个点之后查询它的 (dfn) 序的前驱和后继即可

    这道题因为不需要返回出发点

    所以答案就是极小连通子树的边权和减去联通块直径

    直径拿线段树维护一下就行了

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<set>
    #define rg register
    inline int read(){
    	rg int x=0,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();
    	}
    	return x*fh;
    }
    const int maxn=1e5+5;
    struct asd{
    	int to,nxt,val;
    }b[maxn<<1];
    int h[maxn],tot=1,n,m;
    void ad(rg int aa,rg int bb,rg int cc){
    	b[tot].to=bb;
    	b[tot].nxt=h[aa];
    	b[tot].val=cc;
    	h[aa]=tot++;
    }
    int dfn[maxn],dfnc,siz[maxn],son[maxn],dep[maxn],fa[maxn],tp[maxn],vis[maxn],rk[maxn];
    long long dis[maxn];
    void dfs1(rg int now,rg int lat){
    	fa[now]=lat;
    	dep[now]=dep[lat]+1;
    	siz[now]=1;
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==lat) continue;
    		dis[u]=dis[now]+b[i].val;
    		dfs1(u,now);
    		siz[now]+=siz[u];
    		if(son[now]==0 || siz[u]>siz[son[now]]) son[now]=u;
    	}
    }
    void dfs2(rg int now,rg int top){
    	tp[now]=top;
    	dfn[now]=++dfnc;
    	rk[dfnc]=now;
    	if(son[now]) dfs2(son[now],top);
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==fa[now] || u==son[now]) continue;
    		dfs2(u,u);
    	}
    }
    int getlca(rg int xx,rg int yy){
    	while(tp[xx]!=tp[yy]){
    		if(dep[tp[xx]]<dep[tp[yy]]) std::swap(xx,yy);
    		xx=fa[tp[xx]];
    	}
    	return dep[xx]<dep[yy]?xx:yy;
    }
    long long getdis(rg int xx,rg int yy){
    	return dis[xx]+dis[yy]-2LL*dis[getlca(xx,yy)];
    }
    struct trr{
    	int l,r,zb,yb;
    	long long val;
    }tr[maxn<<2];
    void push_up(rg int da){
    	if(tr[da<<1].zb==-1){
    		tr[da].zb=tr[da<<1|1].zb,tr[da].yb=tr[da<<1|1].yb,tr[da].val=tr[da<<1|1].val;
    	} else if(tr[da<<1|1].zb==-1){
    		tr[da].zb=tr[da<<1].zb,tr[da].yb=tr[da<<1].yb,tr[da].val=tr[da<<1].val;
    	} else {
    		tr[da].zb=tr[da<<1].zb,tr[da].yb=tr[da<<1].yb,tr[da].val=tr[da<<1].val;
    		rg long long tmp=tr[da<<1|1].val;
    		if(tmp>tr[da].val) tr[da].zb=tr[da<<1|1].zb,tr[da].yb=tr[da<<1|1].yb,tr[da].val=tmp;
    		tmp=getdis(tr[da<<1].zb,tr[da<<1|1].zb);
    		if(tmp>tr[da].val) tr[da].zb=tr[da<<1].zb,tr[da].yb=tr[da<<1|1].zb,tr[da].val=tmp;
    		tmp=getdis(tr[da<<1].zb,tr[da<<1|1].yb);
    		if(tmp>tr[da].val) tr[da].zb=tr[da<<1].zb,tr[da].yb=tr[da<<1|1].yb,tr[da].val=tmp;
    		tmp=getdis(tr[da<<1].yb,tr[da<<1|1].zb);
    		if(tmp>tr[da].val) tr[da].zb=tr[da<<1].yb,tr[da].yb=tr[da<<1|1].zb,tr[da].val=tmp;
    		tmp=getdis(tr[da<<1].yb,tr[da<<1|1].yb);
    		if(tmp>tr[da].val) tr[da].zb=tr[da<<1].yb,tr[da].yb=tr[da<<1|1].yb,tr[da].val=tmp;
    	}
    }
    void build(rg int da,rg int l,rg int r){
    	tr[da].zb=tr[da].yb=-1,tr[da].l=l,tr[da].r=r;
    	if(l==r) return;
    	rg int mids=(l+r)>>1;
    	build(da<<1,l,mids),build(da<<1|1,mids+1,r);
    }
    void xg(rg int da,rg int wz,rg int op){
    	if(tr[da].l==tr[da].r){
    		if(op==1) tr[da].zb=tr[da].yb=wz;
    		else tr[da].zb=tr[da].yb=-1;
    		return;
    	}
    	rg int mids=(tr[da].l+tr[da].r)>>1;
    	if(wz<=mids) xg(da<<1,wz,op);
    	else xg(da<<1|1,wz,op);
    	push_up(da);
    }
    long long ans;
    #define sit std::set<int>::iterator
    std::set<int> s;
    int main(){
    	memset(h,-1,sizeof(h));
    	n=read(),m=read();
    	rg int aa,bb,cc;
    	for(rg int i=1;i<n;i++){
    		aa=read(),bb=read(),cc=read();
    		ad(aa,bb,cc),ad(bb,aa,cc);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	rg sit it1,it2;
    	build(1,1,n);
    	for(rg int i=1;i<=m;i++){
    		aa=read();
    		vis[aa]^=1;
    		if(vis[aa]){
    			xg(1,aa,1);
    			s.insert(dfn[aa]);
    			if(s.size()>1){
    				it1=it2=s.upper_bound(dfn[aa]);
    				if(it1==s.end()) it1=s.begin();
    				ans+=getdis(rk[*it1],aa);
    				--it2;
    				if(it2==s.begin()){
    					it2=--s.end();
    				} else {
    					--it2;
    				}
    				ans+=getdis(rk[*it2],aa);
    				ans-=getdis(rk[*it1],rk[*it2]);
    			}
    		} else {
    			xg(1,aa,-1);
    			if(s.size()>1){
    				it1=it2=s.upper_bound(dfn[aa]);
    				if(it1==s.end()) it1=s.begin();
    				ans-=getdis(rk[*it1],aa);
    				--it2;
    				if(it2==s.begin()){
    					it2=--s.end();
    				} else {
    					--it2;
    				}
    				ans-=getdis(rk[*it2],aa);
    				ans+=getdis(rk[*it1],rk[*it2]);
    			}
    			s.erase(dfn[aa]);
    		}
    		printf("%lld
    ",ans-tr[1].val);
    	}
    	return 0;
    }
    
  • 相关阅读:
    mysql分表那些事
    java根据经纬度计算距离
    java Calendar类的使用
    mysql中DATETIME、DATE和TIMESTAMP的区别
    java设计模式
    dubbo教程
    Java算法
    随机产生字符串
    js根据类名获取元素的底层原理
    元素样式的获取
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/14418284.html
Copyright © 2011-2022 走看看