zoukankan      html  css  js  c++  java
  • [BZOJ4003][JLOI2015]城池攻占

    BZOJ
    Luogu

    sol

    补一篇左偏树的题解
    骑士对于树上结点挂链,每次合并所有子树上的骑士后把所有攻击力小于城池防御值的骑士弹掉。
    左偏树维护加乘懒标记
    记得要pushdown
    delete的时候也要记得pushdown!

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int MAX=300005;
    struct edge{int to,next;}a[MAX],b[MAX];
    int head[MAX],cnt,ft[MAX];
    bool type[MAX];
    ll h[MAX],key[MAX],v[MAX],plu[MAX],mul[MAX];
    int n,m,ls[MAX],rs[MAX],dis[MAX],str[MAX],dep[MAX],dead[MAX],up[MAX];
    ll gi()
    {
    	ll x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=-1,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return x*w;
    }
    void cover(int A,ll c,ll j)
    {
    	if (!A) return;
    	key[A]*=c;key[A]+=j;
    	mul[A]*=c;plu[A]*=c;plu[A]+=j;
    }
    void pushdown(int A)
    {
    	cover(ls[A],mul[A],plu[A]);
    	cover(rs[A],mul[A],plu[A]);
    	mul[A]=1;plu[A]=0;
    }
    int merge(int A,int B)
    {
    	if (!A||!B) return A+B;
    	if (key[A]>key[B]) swap(A,B);
    	pushdown(A);pushdown(B);
    	rs[A]=merge(rs[A],B);
    	if (dis[ls[A]]<dis[rs[A]]) swap(ls[A],rs[A]);
    	dis[A]=dis[rs[A]]+1;
    	return A;
    }
    int del(int A)
    {
    	pushdown(A);
    	return merge(ls[A],rs[A]);
    }
    int dfs(int u,int f)
    {
    	dep[u]=dep[f]+1;
    	int A=0,B;
    	for (int e=ft[u];e;e=b[e].next) A=merge(A,b[e].to);
    	for (int e=head[u];e;e=a[e].next)
    	{
    		int v=a[e].to;
    		B=dfs(v,u);
    		A=merge(A,B);
    	}
    	while (key[A]<h[u]&&A)
    	{
    		up[A]=dep[u];++dead[u];
    		A=del(A);
    	}
    	if (type[u]) cover(A,v[u],0);
    	else cover(A,1,v[u]);
    	return A;
    }
    int main()
    {
    	n=gi();m=gi();
    	for (int i=1;i<=n;i++) h[i]=gi();
    	for (int i=2,u;i<=n;i++)
    	{
    		u=gi();
    		a[++cnt]=(edge){i,head[u]};head[u]=cnt;
    		type[i]=gi();v[i]=gi();
    	}
    	cnt=0;
    	for (int i=1;i<=m;i++)
    	{
    		key[i]=gi();str[i]=gi();
    		b[++cnt]=(edge){i,ft[str[i]]};ft[str[i]]=cnt;
    	}
    	dfs(1,0);
    	for (int i=1;i<=n;i++) printf("%d
    ",dead[i]);
    	for (int j=1;j<=m;j++) printf("%d
    ",dep[str[j]]-up[j]);
    	return 0;
    }
    
  • 相关阅读:
    软件概要设计
    项目文件-搭建工程
    select标签中设置只读几种解决方案
    PHP ob缓冲区函数的使用
    laravel笔记
    ubuntu系统更新命令
    RBAC权限控制系统
    laravel 数据库获取值的常用方法
    php中获取数据 php://input、$_POST与$GLOBALS['HTTP_RAW_POST_DATA']三者的区别
    php 文件上传 $_FILES 错误码
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8461464.html
Copyright © 2011-2022 走看看