Loading

noip模拟15

A. 夜莺与玫瑰

分类讨论\(a\)\(\dfrac{n}{2}\)\(b\)\(\dfrac{m}{2}\)的关系..
然后得到式子:

\[\Sigma_{a=1}^{n-1} \Sigma_{b=1}^{m-1}[gcd(a,b)==1)]((n-a)(m-b)-max(n-2*a,0)*max(m-2*b,0)) \]

于是前缀和优化即可..

B. 影子

我们可以从小规模向大规模转移..
维护每个并查集内的权值最大的链,然后考虑这个并查集向四周扩展即可..

B_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define re register ll
#define lf double
#define mp make_pair
const ll N=1e5+50;
inline void read(ll &ss)
{
	ss=0; bool cit=0; char ch;
	while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
	while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
	if(cit) ss=-ss;
}
// 注意清零
ll alls,ts,n,cnt,ans;
bool vis[N];
ll value[N],head[N],son[N],top[N],siz[N],id[N],rk[N],path[N],fa[N],dep[N],father[N];
struct I { ll u,v,w,nxt; } a[N*2];
struct II { ll num,dad,val; } pot[N];
struct III { ll p1,p2,len; } S[N];
ll find(ll x) { return x==father[x] ? x : (father[x]=find(father[x])) ; }
bool comp(II aa,II bb) { return aa.val==bb.val ? aa.num<bb.num : aa.val>=bb.val ; }
void add(ll u,ll v,ll w)
{
	a[++ts].u=u; a[ts].v=v; a[ts].w=w;
	a[ts].nxt=head[u]; head[u]=ts;
}
void dfs1(ll now,ll dad,ll depth)
{
	fa[now]=dad; dep[now]=depth;
	siz[now]=1; 
	for(re i=head[now];i;i=a[i].nxt)
	{
		if(a[i].v==dad) continue;
		path[a[i].v]=a[i].w+path[now]; 
		dfs1(a[i].v,now,depth+1);
		siz[now]+=siz[a[i].v];
		if(siz[a[i].v]>siz[son[now]]) son[now]=a[i].v;
	}
	return ;
}
void dfs2(ll now,ll high)
{
	top[now]=high; 
	id[now]=++cnt; rk[cnt]=now;
	if(!son[now]) return ;
	dfs2(son[now],high);
	for(re i=head[now];i;i=a[i].nxt)
	{
		if(a[i].v==fa[now] or a[i].v==son[now]) continue;
		dfs2(a[i].v,a[i].v);
	}
	return ;
}
ll lca(ll x,ll y)
{
	while(top[x]!=top[y]) 
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	return dep[x]<dep[y] ? x : y ;
}
void work(ll now)
{
	vis[now]=1; S[now].p1=S[now].p2=now;
	ll l1,l2,r1,r2,dad,dis; father[now]=now;
	for(re i=head[now];i;i=a[i].nxt)
	{
		if(vis[a[i].v]) 
		{
			father[now]=find(father[now]); father[a[i].v]=find(father[a[i].v]);
			if(father[now]==father[a[i].v]) continue; // 目测没有什么用的一句话..
			l1=S[father[now]].p1,l2=S[father[now]].p2;
			r1=S[father[a[i].v]].p1,r2=S[father[a[i].v]].p2;
			if(S[father[now]].len>S[father[a[i].v]].len)
				S[father[a[i].v]].p1=l1,S[father[a[i].v]].p2=l2,S[father[a[i].v]].len=S[father[now]].len;
			father[father[now]]=father[a[i].v]; father[now]=find(father[now]);
			dad=lca(l1,r1); dis=path[l1]+path[r1]-path[dad]*2;
			if(dis>S[father[now]].len) 
				S[father[now]].len=dis,S[father[now]].p1=l1,S[father[now]].p2=r1;
			dad=lca(l1,r2); dis=path[l1]+path[r2]-path[dad]*2;
			if(dis>S[father[now]].len) 
				S[father[now]].len=dis,S[father[now]].p1=l1,S[father[now]].p2=r2;
			dad=lca(l2,r1); dis=path[l2]+path[r1]-path[dad]*2;
			if(dis>S[father[now]].len) 
				S[father[now]].len=dis,S[father[now]].p1=l2,S[father[now]].p2=r1;
			dad=lca(l2,r2); dis=path[l2]+path[r2]-path[dad]*2;
			if(dis>S[father[now]].len) 
				S[father[now]].len=dis,S[father[now]].p1=l2,S[father[now]].p2=r2;
		}
//		cout<<"len:"<<S[father[now]].len<<" "<<value[now]<<" \n";
		ans=max(ans,S[father[now]].len*value[now]);
	}
	return ;
}
signed main()
{
//	freopen("0.in","r",stdin);
//	freopen("out","w",stdout);
	#define fill(x) memset(x,0,sizeof x);
	read(alls);
	while(alls--)
	{	
		fill(vis); fill(value); fill(head); fill(son); fill(top); fill(siz); fill(id); fill(rk); 
		fill(path); fill(fa); fill(dep); fill(father); 
		read(n); ll u,v,w;
		for(re i=1;i<=n;i++) { read(value[i]); pot[i].num=i; pot[i].dad=i; pot[i].val=value[i]; }
		for(re i=1;i<=n-1;i++) { read(u); read(v); read(w); add(u,v,w); add(v,u,w); }
		dfs1(1,0,1); dfs2(1,1); sort(pot+1,pot+1+n,comp);
		for(re i=1;i<=n;i++) work(pot[i].num);
		printf("%lld\n",ans);
		for(ll i=1;i<=n;i++) pot[i].num=pot[i].dad=pot[i].val=0;
		for(ll i=1;i<=ts;i++) a[i].u=a[i].v=a[i].w=a[i].nxt=0;
		for(ll i=1;i<=n;i++) S[i].p1=S[i].p2=S[i].len=0;
		ans=0,ts=0,cnt=0;
	}
	return 0;
}
/*
1 3
1 2 3
1 2 1
1 3 2

 */

C. 玫瑰花精

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll int
	#define ull unsigned ll 
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memcpy(x,y,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=2e5+50;

ll n,m;
ll pos[N*5];
struct I { ll lx,rx,len,lp,rp,lc,rc; } tr[N*20];
// lx 和左边结合的长度,rx 和右边结合的长度,len 中间的最优解长度
// lp 和左边结合的端点,rp 和右边结合的端点,lc 中间最优解的左端点,rc 中间最优解的右端点
inline void pushup(ll x,ll l,ll r){
	ll mid=(l+r)>>1;
	tr[x].lx=tr[x<<1].lx,tr[x].lp=tr[x<<1].lp;
	if(tr[x].lp==mid) tr[x].lx+=tr[x<<1|1].lx,tr[x].lp=tr[x<<1|1].lp;
	tr[x].rx=tr[x<<1|1].rx,tr[x].rp=tr[x<<1|1].rp;
	if(tr[x].rp==mid+1) tr[x].rx+=tr[x<<1].rx,tr[x].rp=tr[x<<1].rp;
	tr[x].len=tr[x<<1].rx+tr[x<<1|1].lx,tr[x].lc=tr[x<<1].rp,tr[x].rc=tr[x<<1|1].lp;
	if( ((tr[x].len+1)>>1) <= ((tr[x<<1].len+1)>>1) )
		tr[x].len=tr[x<<1].len,tr[x].lc=tr[x<<1].lc,tr[x].rc=tr[x<<1].rc;
	if( ((tr[x].len+1)>>1) < ((tr[x<<1|1].len+1)>>1) )
		tr[x].len=tr[x<<1|1].len,tr[x].lc=tr[x<<1|1].lc,tr[x].rc=tr[x<<1|1].rc;
}                                    
void update(ll x,ll l,ll r,ll pos,ll w){
	if(l==r){
		if(w&1){
			tr[x].lx=0,tr[x].rx=0,tr[x].len=0,
			tr[x].rp=pos+1,tr[x].lp=pos-1,tr[x].lc=pos+1,tr[x].rc=pos-1;
		}
		else{
			tr[x].lx=1,tr[x].rx=1,tr[x].len=1,
			tr[x].lp=pos,tr[x].rp=pos,tr[x].lc=pos,tr[x].rc=pos;
		}
		return ;
	}
	ll mid=(l+r)>>1;
	if(pos<=mid) update(x<<1,l,mid,pos,w);
	else update(x<<1|1,mid+1,r,pos,w);
	pushup(x,l,r);
}
void build(ll x,ll l,ll r){
	tr[x].lx=r-l+1,tr[x].rx=r-l+1,tr[x].len=r-l+1,
	tr[x].lp=r,tr[x].rp=l,tr[x].lc=l,tr[x].rc=r;
	if(l==r) return ;
	ll mid=(l+r)>>1;
	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
}
signed main()
{
	n=read(),m=read(),build(1,1,n);
	ll temp,dis1,dis2,dis,opt,id;
	for(re i=1;i<=m;i++){
		opt=read(),id=read();
		if(opt&1){
			if(tr[1].lc==1 or tr[1].lx>=((tr[1].len+1)>>1)) pos[id]=1;
			else if(tr[1].rc==n or tr[1].rx>((tr[1].len+1)>>1)) pos[id]=n;
			else pos[id]=(tr[1].lc+tr[1].rc)>>1;	
			update(1,1,n,pos[id],1); printf("%d\n",pos[id]);
		}
		else update(1,1,n,pos[id],2);
	}
	exit(0);
}
posted @ 2021-08-04 21:34  AaMuXiiiiii  阅读(42)  评论(1)    收藏  举报