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

    嘟嘟嘟

     

    暴力不难想:一种是以每一个骑士为主,一步步向上爬直到死了;一种是以每一个城池为主,统计哪些骑士在这座城池中死了,然后剩下的骑士再转移到他的父亲节点。

    考虑优化:因为城池构成了一个树形结构,相对于骑士来说结构比较固定。因此我们想办法优化第二个暴力:每一个节点建一个小根堆,一直弹出堆顶直到堆顶骑士的战斗力>=防御值,然后把剩下的骑士都转移到他的父亲节点取。所以说,父亲节点的骑士是由他的子节点的骑士合并而来的。那么这个堆还要支持合并,左偏树是一个不错的选择。

    左偏树是可以打标记的,因此修改就和线段树有点像,打一个lazy标记,然后处理到这个节点的时候pushdown就行了。

    最后说一下统计答案:每一个城池牺牲多少人好办,开一计数数组就解决了。关键是统计每一个骑士攻占了多少城池。原来我的做法是每攻占了一个城池,就给左偏树的所有骑士++,实际上有一个更好的办法:维护树中每一个节点的深度,则一个骑士攻占的城池数量就是第一个攻占的城池的深度减去死的城池的深度。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 3e5 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m;
     38 ll h[maxn], v[maxn]; 
     39 bool a[maxn];
     40 ll s[maxn];
     41 int c[maxn];
     42 int ans1[maxn], ans2[maxn];
     43 struct Edge
     44 {
     45     int nxt, to;
     46 }e[maxn];
     47 int head[maxn], ecnt = 0;
     48 void addEdge(int x, int y)
     49 {
     50     e[++ecnt] = (Edge){head[x], y};
     51     head[x] = ecnt;
     52 }
     53 
     54 int root[maxn], ls[maxn], rs[maxn], dis[maxn], dep[maxn];
     55 ll lzy_mul[maxn], lzy_add[maxn];
     56 void Sign(int now, ll mul, ll add)
     57 {
     58     if(!now) return;
     59     s[now] *= mul; s[now] += add;
     60     lzy_mul[now] *= mul; lzy_add[now] *= mul; lzy_add[now] += add;
     61 }
     62 void pushdown(int now)
     63 {
     64     Sign(ls[now], lzy_mul[now], lzy_add[now]);
     65     Sign(rs[now], lzy_mul[now], lzy_add[now]);
     66     lzy_mul[now] = 1; lzy_add[now] = 0;
     67 }
     68 int merge(int x, int y)
     69 {
     70     if(!x || !y) return x | y;
     71     pushdown(x); pushdown(y);
     72     if(s[x] > s[y]) swap(x, y);
     73     rs[x] = merge(rs[x], y);
     74     if(dis[ls[x]] < dis[rs[x]]) swap(ls[x], rs[x]);
     75     dis[x] = dis[rs[x]] + 1;
     76     return x;
     77 }
     78 int Del(int now)
     79 {
     80     return merge(ls[now], rs[now]);
     81 }
     82 
     83 void dfs(int now)
     84 {
     85     for(int i = head[now]; i; i = e[i].nxt)
     86     {
     87         dep[e[i].to] = dep[now] + 1;
     88         dfs(e[i].to);
     89         root[now] = merge(root[now], root[e[i].to]);
     90     }
     91     while(root[now] && s[root[now]] < h[now])
     92     {
     93         pushdown(root[now]);
     94         ans1[now]++; 
     95         ans2[root[now]] = dep[c[root[now]]] - dep[now];
     96         root[now] = Del(root[now]);
     97     }
     98     if(a[now]) Sign(root[now], v[now], 0);
     99     else Sign(root[now], 1, v[now]);
    100 }
    101 
    102 int main()
    103 {
    104     n = read(); m = read();
    105     for(int i = 1; i <= n; ++i) h[i] = read();
    106     for(int i = 2; i <= n; ++i)
    107     {
    108         int x = read(); a[i] = (bool)read(); v[i] = read();
    109         addEdge(x, i);
    110     }
    111     for(int i = 1; i <= m; ++i)
    112     {
    113         s[i] = read(); c[i] = read();
    114         lzy_mul[i] = 1;
    115         root[c[i]] = merge(root[c[i]], i);
    116     }
    117     dep[1] = 1; dfs(1);
    118     while(root[1])
    119     {
    120         pushdown(root[1]);
    121         ans2[root[1]] = dep[c[root[1]]];
    122         root[1] = Del(root[1]);
    123     }
    124     for(int i = 1; i <= n; ++i) write(ans1[i]), enter;
    125     for(int i = 1; i <= m; ++i) write(ans2[i]), enter;
    126     return 0;
    127 }
    View Code
  • 相关阅读:
    交换排序------冒泡法 及其优化
    [编程题]最大和子矩阵
    [编程题] N阶楼梯上楼问题
    2017年东北大学计算机专业考博 面试编程题(某教授 实验室)
    幸运的袋子 (牛客网 16年网易内推 编程题)
    OpenvSwitch代码分析之bridge和port
    阅读书籍---程序员必读系列
    嵌入式开发之davinci--- 8168 电源调试总结
    嵌入式开发之davinci--- 8148/8168/8127 中的添加算饭scd 场景检测 文档简介
    嵌入式开发之davinci--- 8148/8168/8127 中的图像缩放sclr、swms之后出现图像视频卡顿、屏幕跳跃的问题
  • 原文地址:https://www.cnblogs.com/mrclr/p/9801985.html
Copyright © 2011-2022 走看看