您的位置:首页 > 其它

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

2016-04-30 14:02 519 查看
蒟蒻想起来自己还不会可并堆诶

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



#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
,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
;
long long h
;
long double val
,K
,B
;
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
[13];
long double maxv
[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
,ans2
;

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
;

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
;

int n,m;
int fa
,deg
,depth
;
ll h
,f
,a
;
int ans1
,ans2
;
int S
;
int Stack
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: