[三进制倍增 || 可并堆] BZOJ 4003 [JLOI2015]城池攻占

蒟蒻想起来自己还不会可并堆诶

出题人卡倍增,那么淡定的写了个三进制倍增


[三进制倍增 || 可并堆] BZOJ 4003 [JLOI2015]城池攻占_第1张图片


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<limits>
#include<cstring>
#define V G[p].v
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(long long &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline int dcmp(long double a,long double b){
	if (fabs(a-b)<1e-6) return 0;
	if (a<b) return -1;
	return 1;
}

const int N=300005;

struct edge{
	int u,v;
	int f,a;
	int next;
};

edge G[N*2];
int head[N],inum;

inline void add(int u,int v,int f,int a,int p)
{
	G[p].u=u; G[p].v=v; G[p].f=f; G[p].a=a; G[p].next=head[u]; head[u]=p;
}

int n,m;
int depth[N];
long long h[N];
long double val[N],K[N],B[N];
long double maximum=-1e100;

void dfs(int u,long double k,long double b)
{
	val[u]=k*h[u]+b; K[u]=k; B[u]=b;
	maximum=max(maximum,val[u]);
	for (int p=head[u];p;p=G[p].next)
	{
		depth[V]=depth[u]+1;
		if (G[p].f==1)
			dfs(V,k*G[p].a,b);
		else
			dfs(V,k,k*G[p].a+b);
	}
}

int fat[N][13];
long double maxv[N][13];

inline void Pre()
{
	for (int k=1;k<13;k++)
		for (int i=1;i<=n;i++)
			fat[i][k]=fat[fat[fat[i][k-1]][k-1]][k-1];
	for (int k=1;k<13;k++) maxv[0][k]=(numeric_limits<long double>::max)();
	for (int i=1;i<=n;i++)
		maxv[i][0]=val[i];
	for (int k=1;k<13;k++)
		for (int i=1;i<=n;i++)
			maxv[i][k]=max(max(maxv[i][k-1],maxv[fat[i][k-1]][k-1]),maxv[fat[fat[i][k-1]][k-1]][k-1]);
}

int ans1[N],ans2[N];

int main()
{
	int iv,f,a;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n); read(m);
	for (int i=1;i<=n;i++) read(h[i]);
	for (int i=2;i<=n;i++)
		read(iv),read(f),read(a),add(iv,i,f,a,++inum),fat[i][0]=iv;
	depth[1]=1;
	dfs(1,1,0);
	Pre();
	for (int i=1;i<=m;i++)
	{
		int S,iC,T; long double C;
		read(iC); read(S); T=S; C=iC;
		C=K[S]*C+B[S];
		for (int k=12;k>=0;k--)
		{
			if (dcmp(max(maxv[T][k],maxv[fat[T][k]][k]),C)<=0)
				T=fat[fat[T][k]][k];
			if (dcmp(maxv[T][k],C)<=0)
				T=fat[T][k];
		}
		ans1[i]=depth[S]-depth[T];
		ans2[T]++;
	}
	for (int i=1;i<=n;i++) printf("%d\n",ans2[i]);
	for (int i=1;i<=m;i++) printf("%d\n",ans1[i]);
	return 0;
}

UPD:random heap 很兹瓷哇


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline void read(ll &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=300005;

int ran(){static int x=31253125;x+=(x<<4)+1;return x&65536;}

struct node{
	node *l,*r;
	ll key; int idx;
	ll k,b;
	void modify(ll _k,ll _b){
		key=key*_k+_b;
		k=k*_k; b=_k*b+_b;
	}
	void pushdown(){
		if (!(k==1 && b==0)) { if (l) l->modify(k,b); if (r) r->modify(k,b); k=1; b=0; }
	}
}nodes[N];

node *M(node *p,node *q){
	if  (!p||!q) return (p?p:q);
	if (p->key>q->key) return M(q,p);
	p->pushdown(); ran()?p->r=M(p->r,q):p->l=M(p->l,q);
	return p;
}
node *root[N];

int n,m;
int fa[N],deg[N],depth[N];
ll h[N],f[N],a[N];
int ans1[N],ans2[N];
int S[N];
int Stack[N],pnt;

int main()
{
	ll c; int s;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n); read(m); memset(ans2,-1,sizeof(ans2));
	for (int i=1;i<=n;i++) read(h[i]);
	for (int i=2;i<=n;i++) read(fa[i]),read(f[i]),read(a[i]),deg[fa[i]]++,depth[i]=depth[fa[i]]+1;
	for (int i=1;i<=n;i++) root[i]=NULL;
	for (int i=1;i<=m;i++)
	{
		read(c); read(s); S[i]=s;
		nodes[i].key=c; nodes[i].l=nodes[i].r=NULL; nodes[i].idx=i; nodes[i].k=1; nodes[i].b=0;
		root[s]=M(root[s],nodes+i);
	}
	for (int i=1;i<=n;i++) if (!deg[i]) Stack[++pnt]=i;
	while (pnt){
		s=Stack[pnt--];
		while (root[s] && root[s]->key<h[s])
		{
			ans1[s]++; ans2[root[s]->idx]=depth[S[root[s]->idx]]-depth[s];
			root[s]->pushdown(); root[s]=M(root[s]->l,root[s]->r);
		}
		if (root[s]) 
		{
			if (f[s]==0) root[s]->modify(1,a[s]);
			if (f[s]==1) root[s]->modify(a[s],0);
		}
		if (fa[s]) 
		{
			root[fa[s]]=M(root[fa[s]],root[s]);
			if (!(--deg[fa[s]])) Stack[++pnt]=fa[s];
		}
	}
	for (int i=1;i<=m;i++) if (ans2[i]==-1) ans2[i]=depth[S[i]]+1;
	for (int i=1;i<=n;i++) printf("%d\n",ans1[i]);
	for (int i=1;i<=m;i++) printf("%d\n",ans2[i]);
	return 0;
}


你可能感兴趣的:([三进制倍增 || 可并堆] BZOJ 4003 [JLOI2015]城池攻占)