牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

链接:https://ac.nowcoder.com/acm/problem/15706

现在需要您来帮忙维护这个名册,支持下列 4 种操作:

  1. 插入新人名 si,声望为 a
  2. 给定名字前缀 pi 的所有人的声望值变化 di
  3. 查询名字为 sj 村民们的声望值的和(因为会有重名的)
  4. 查询名字前缀为 pj 的声望值的和

题解:一个非常明显的线段树操作,前缀可以看作是区间更新,区间查询,给定名字就是单点更新,单点查询,字典树上dfs序可以得到将树型结构变成一个线性的结构,然后用线段树维护即可,比较好的码力题了

/**

*        ┏┓    ┏┓

  •        ┏┛┗━━━━━━━┛┗━━━┓
  •        ┃       ┃  
  •        ┃   ━    ┃
  •        ┃ >   < ┃
  •        ┃       ┃
  •        ┃... ⌒ ...  ┃
  •        ┃       ┃
  •        ┗━┓   ┏━┛
  •          ┃   ┃ Code is far away from bug with the animal protecting          
  •          ┃   ┃ 神兽保佑,代码无bug
  •          ┃   ┃           
  •          ┃   ┃       
  •          ┃   ┃
  •          ┃   ┃           
  •          ┃   ┗━━━┓
  •          ┃       ┣┓
  •          ┃       ┏┛
  •          ┗┓┓┏━┳┓┏┛
  •           ┃┫┫ ┃┫┫
  •           ┗┻┛ ┗┻┛

    */

    // warm heart, wagging tail,and a smile just for you!

    //

    // ooOoo

    // o8888888o

    // 88" . "88

    // (| -_- |)

    // O\ = /O

    // /---'\____ // .' \| |// .

    // / ||| : |||//

    // / ||||| -:- |||||-

    // | | \ - /// | |

    // | _| ''---/'' | |

    // \ .-_
    - /-. /

    // . .' /--.--\ . . __

    // ."" '< .___\_<|>_/___.' >'"". // | | : - `.;\ _ /;./ - : | |

    // \ \ -. \_ __\ /__ _/ .- / /

    // ======-.____-.
    _
    /
    .-____.-'====== // =---='

    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    // 佛祖保佑 永无BUG

include

include

include

include

include

include

include

include

include

include

include

using namespace std;

typedef long long LL;

typedef pair<int, int> pii;

typedef unsigned long long uLL;

define ls rt<<1

define rs rt<<1|1

define lson l,mid,rt<<1

define rson mid+1,r,rt<<1|1

define bug printf("*********\n")

define FIN freopen("input.txt","r",stdin);

define FON freopen("output.txt","w+",stdout);

define IO ios::sync_with_stdio(false),cin.tie(0)

define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"

define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"

define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"

const int maxn = 3e5 + 5;

const int INF = 0x3f3f3f3f;

const int mod = 1e9 + 7;

const double Pi = acos(-1);

LL gcd(LL a, LL b) {

return b ? gcd(b, a % b) : a;

}

LL lcm(LL a, LL b) {

return a / gcd(a, b) * b;

}

double dpow(double a, LL b) {

double ans = 1.0;

while(b) {

if(b % 2)ans = ans * a;

a = a * a;

b /= 2;

} return ans;

}

LL quick_pow(LL x, LL y) {

LL ans = 1;

while(y) {

if(y & 1) {

ans = ans * x % mod;

} x = x * x % mod;

y >>= 1;

} return ans;

}

struct Trie {

int nxt[maxn][26], tot;

int in[maxn], out[maxn], time_tag;

void init() {

memset(nxt, 0, sizeof(nxt));

tot = 1;

time_tag = 0;

}

void insert(string str) {

int p = 1;

int len = str.length();

for(int i = 0; i < len; i++) {

int ch = str[i] - 'a';

if(!nxt[p][ch]) {

nxt[p][ch] = ++tot;

}

p = nxt[p][ch];

}

}

int query(string str) {

int p = 1;

int len = str.length();

for(int i = 0; i < len; i++) {

int ch = str[i] - 'a';

if(!nxt[p][ch]) {

return 0;

}

p = nxt[p][ch];

}

return p;

}

void dfs(int u) {

in[u] = ++time_tag;

for(int i = 0; i < 26; i++) {

if(nxt[u][i]) {

dfs(nxt[u][i]);

}

}

out[u] = time_tag;

}

} trie;

LL sum[maxn << 2];

int lazy[maxn << 2];

int cnt[maxn << 2];

void push_up(int rt) {

sum[rt] = sum[ls] + sum[rs];

cnt[rt] = cnt[ls] + cnt[rs];

}

void build(int l, int r, int rt) {

sum[rt] = lazy[rt] = 0;

if(l == r) return;

int mid = (l + r) >> 1;

build(lson);

build(rson);

}

void push_down(int rt, int len) {

if(lazy[rt]) {

lazy[ls] += lazy[rt];

lazy[rs] += lazy[rt];

    sum[ls] += lazy[rt] * cnt[ls];
sum[rs] += lazy[rt] * cnt[rs]; lazy[rt] = 0;
}

}

void update_pos(int pos, int val, int l, int r, int rt) {

if(l == r) {

sum[rt] += val;

cnt[rt]++;

return;

}

int mid = (l + r) >> 1;

push_down(rt, r - l + 1);

if(pos <= mid) update_pos(pos, val, lson);

else update_pos(pos, val, rson);

push_up(rt);

}

void update(int L, int R, int val, int l, int r, int rt) {

if(L <= l && r <= R) {

sum[rt] += cnt[rt] * val;

lazy[rt] += val;

return;

}

int mid = (l + r) >> 1;

push_down(rt, r - l + 1);

if(L <= mid) update(L, R, val, lson);

if(R > mid) update(L, R, val, rson);

push_up(rt);

}

LL query(int L, int R, int l, int r, int rt) {

if(L <= l && r <= R) {

return sum[rt];

}

int mid = (l + r) >> 1;

push_down(rt, r - l + 1);

LL ans = 0;

if(L <= mid) ans += query(L, R, lson);

if(R > mid) ans += query(L, R, rson);

return ans;

}

int op[maxn];

char buf[maxn];

string str[maxn];

int val[maxn];

int main() {

ifndef ONLINE_JUDGE

FIN

endif

int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d %s", &op[i], buf);
str[i] = buf;
if(op[i] <= 2) {
scanf("%d", &val[i]);
}
}
trie.init();
for(int i = 1; i <= n; i++) {
if(op[i] == 1) {
trie.insert(str[i]);
// cout << str[i] << endl;
}
}
trie.dfs(1);
// bug;
int tot = trie.tot;
// debug1(tot);
build(1, tot, 1);
for(int i = 1; i <= n; i++) {
if(op[i] == 1) {
int u = trie.query(str[i]);
int pos = trie.in[u];
// debug1(pos);
update_pos(pos, val[i], 1, tot, 1);
// bug;
} else if(op[i] == 2) {
int u = trie.query(str[i]);
if(u) {
int l = trie.in[u];
int r = trie.out[u];
update(l, r, val[i], 1, tot, 1);
}
} else if(op[i] == 3) {
int u = trie.query(str[i]);
if(u) {
int l = trie.in[u];
int r = trie.in[u];
LL ans = query(l, r, 1, tot, 1);
printf("%lld\n", ans);
} else {
printf("0\n");
}
} else if(op[i] == 4) {
int u = trie.query(str[i]);
if(u) {
int l = trie.in[u];
int r = trie.out[u];
LL ans = query(l, r, 1, tot, 1);
printf("%lld\n", ans);
} else {
printf("0\n");
} }
}
return 0;

}

牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)的更多相关文章

  1. 牛客多校第三场 G Removing Stones(分治+线段树)

    牛客多校第三场 G Removing Stones(分治+线段树) 题意: 给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半 题解: 分治+线段树 线段树维护最 ...

  2. 牛客~~wannafly挑战赛19~A 队列

    链接:https://www.nowcoder.com/acm/contest/131/A来源:牛客网 题目描述 ZZT 创造了一个队列 Q.这个队列包含了 N 个元素,队列中的第 i 个元素用 Qi ...

  3. 牛客Wannafly挑战赛23 B.游戏

    游戏 题目描述 小N和小O在玩游戏.他们面前放了n堆石子,第i堆石子一开始有ci颗石头.他们轮流从某堆石子中取石子,不能不取.最后无法操作的人就输了这个游戏.但他们觉得这样玩太无聊了,更新了一下规则. ...

  4. 牛客练习赛 29 E 位运算?位运算!(线段树)

    题目链接  牛客练习赛29E 对$20$位分别建立线段树.首先$1$和$2$可以合起来搞(左移右移其实是等效的) 用个lazy标记下.转移的时候加个中间变量. $3$和$4$其实就是区间$01$覆盖操 ...

  5. 牛客小白月赛16 H 小阳的贝壳 (差分+线段树)

    链接:https://ac.nowcoder.com/acm/contest/949/H来源:牛客网 题目描述 小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 colico ...

  6. 牛客小白月赛12 H 华华和月月种树 (离线dfs序+线段树)

    链接:https://ac.nowcoder.com/acm/contest/392/H 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 131072K,其他语言2621 ...

  7. HDU 3974 Assign the task(DFS序+线段树单点查询,区间修改)

    描述There is a company that has N employees(numbered from 1 to N),every employee in the company has a ...

  8. 牛客 Wannafly 挑战赛26D 禁书目录 排列组合 概率期望

    原文链接https://www.cnblogs.com/zhouzhendong/p/9781060.html 题目传送门 - NowCoder Wannafly 26D 题意 放一放这一题原先的题面 ...

  9. 【牛客Wannafly挑战赛12】 题解

    传送门:https://www.nowcoder.com/acm/contest/79#question 说是比赛题解,其实我只会前三题: 后面的一定补 T1 题意,在一个长度为n的时间内,问如何选择 ...

随机推荐

  1. cmd 命令重启远程服务器

    今天,连接服务器突然无法连接远程桌面,更无法重新启动机器,先进行了ping  操作: 机器运行正常... 后通过远程软件发现,可以用命令...这是一个新发现  …^ .^ 1.输入cmd  运行正常. ...

  2. PyCharm切换Python版本

    由于代码格式问题,很多情况下需要我们去切换Python版本,那么在当下火爆的PyCharm中是如何切换Python版本的呢? 打开File菜单,选择Settings: 打开Settings窗口后,选择 ...

  3. shell学习(22)- comm

    1.预备知识 comm命令可用于比较两个已排序的文件.它可以显示出第一个文件和第二个文件所独有的行以及这两个文件所共有的行.该命令有一些选项可以禁止显示指定的列,以便于执行交集和求差操作. 交集(in ...

  4. SpingMVC ModelAndView, Model,Control以及参数传递总结

    1.web.xml 配置: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <servlet>     <servlet-name>dispatcher& ...

  5. java把Word文件转成html的字符串返回出去

    1.需求是把前端上传的word文件解析出来,生成html的字符串返回给前端去展示,Word里面的图片可以忽略不显示,所以这段代码去掉了解析图片的代码 package com.lieni.core.ut ...

  6. 2019-3-27-win10-uwp-动画移动滑动条的滑块

    title author date CreateTime categories win10 uwp 动画移动滑动条的滑块 lindexi 2019-03-27 10:51:32 +0800 2019- ...

  7. Java练习 SDUT - 2669_2-2 Time类的定义

    2-2 Time类的定义 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 通过本题目的练习可以掌握类与对象的定义: 设计 ...

  8. Libevent:2设置

    Libevent有一些整个进程共享的全局设置.这些设置会影响到整个的库.因此必须在调用Libevent其他函数之前进行设置,否则,LIbevent就会陷入不一致的状态. 一:Libevent中的日志信 ...

  9. 干货|Spring Cloud Bus 消息总线介绍

    继上一篇 干货|Spring Cloud Stream 体系及原理介绍 之后,本期我们来了解下 Spring Cloud 体系中的另外一个组件 Spring Cloud Bus (建议先熟悉 Spri ...

  10. shell学习(20)- xargs

    xargs 是给命令传递参数的一个过滤器,也是组合多个命令的一个工具. xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据. xargs 也可以将单行或多 ...