GDCPC2009--H(线段树)

本文介绍了一款名为《西游记Online》的游戏背后的算法挑战。游戏包含多个区域及城堡,玩家需处理城堡的重要性值变化及特定路径切断后的最大最小值计算。文章详细解析了如何使用线段树和深度优先搜索解决这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Westward JourneyOnline

(Input File: h.in /Standard Output)

 

“Westward Journey” is one of the most popular online gamesin China, which is developed and run by NIE. The game is based on the famousand romantic Chinese classical fiction “Journey to the West”, and the well-knowfilm by Stephen Chow. The story behind “Westward Journey” is fantasy and thusattracts many players.

The gamecontains many regions, and different regions are ruled by different dominators.One of the regions which named “Tree World” is now ruled by a monster. There areN castles in this region, and each of them has its importance value (a positiveinteger not larger than 108). The castles are connected by (N – 1)bidirectional roads. The roads make all the castles connected (that means youcan travel between any two castles of them). The importance values of thecastles are variable. Now, the monster wants to know something if he destroysone of the roads. In detail, you are to handle totally Q instructions: each ofthem can be one of the following forms.

 

CHANGE i w

The importance value of the ith castle was changed to w (1≤w≤108).

QUERY j

Output min1 × max1 + min2 × max2

Explanations: The jth road can divide the “Tree World” into two connected components, named part1 and part2. Here,

min1: the minimum importance value in part1;

max1: the maximum importance value in part1;

min2: the minimum importance value in part2;

max2: the maximum importance value in part2;

 

Input:

The firstline contains an integer T (T ≤10), the number of test cases.

For eachtest case, the first line contains two integers N (2 ≤ N ≤ 100000) and Q (1 ≤ Q≤ 100000), indicating the number ofcastles and instructions.

Thefollowing line contains N integers (positive integer not larger than 108),indicating the initial importance value of each castle (castles are numberedfrom 1 to N).

Thefollowing (N – 1) lines each contains two integers u and v, indicating castle uand castle v are connected directly by a bidirectional road (the roads arenumbered from 1 to N - 1).

Thefollowing Q lines each contains an instruction according to the specificationabove.

 

 

Output:

For each“QUERY” instruction, output the result on a separate line.

 

SampleInput:

1

53

12 3 4 5

12

23

34

45

QUERY1

CHANGE1 10

QUERY1

 

SampleOutput:

11

110

题意:给出一棵树,每个节点有点权。两种操作:一种是更改点权。另一种是询问如果删掉某条边后两棵子树的最大值最小值之积的和、

思路:TLE了好多发、、、最后因为cout的原因,改为printf就AC,囧!!!

    通过时间戳建立线段树,则每颗子树在线段树上是连续的区间。这样就很好想了,两部分,一部分在线段树上是连续的区间。另一部分就是线段树的剩余部分。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long int
#define inf 0x3f3f3f3f
#define maxn 100800
#define maxm 200160
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int key[maxn],a[maxn],pos[maxn];
int pre[maxn],Left[maxn],Right[maxn];
int first[maxn];
int vv[maxm],nxt[maxm];
int e,cnt;
int Min1,Min2,Max1,Max2;
struct Edge
{
    int from,to;
}edge[maxn];
void init()
{
    memset(first,-1,sizeof(first));
    e = cnt = 0;
}
void addedge(int u,int v)
{
    vv[e] = v;  nxt[e] = first[u];  first[u] = e++;
    vv[e] = u;  nxt[e] = first[v];  first[v] = e++;
}
inline int min(int a,int b)
{
    return a>b?b:a;
}
inline int max(int a,int b)
{
    return a>b?a:b;
}

struct ST
{
    int l,r,Min,Max;
}st[maxn<<2];
void PushUp(int id)
{
    st[id].Max = max(st[id<<1].Max,st[id<<1|1].Max);
    st[id].Min = min(st[id<<1].Min,st[id<<1|1].Min);
}
void buildtree(int id,int l,int r)
{
    st[id].l = l,st[id].r = r;
    if(l == r)
    {
        st[id].Min = st[id].Max = key[l];
        return;
    }
    int mid = (l+r) >> 1;
    buildtree(lson);
    buildtree(rson);
    PushUp(id);
}
void Update(int id,int pos,int k)
{
    if(st[id].l == pos && st[id].r == pos)
    {
        st[id].Min = st[id].Max = k;
        return;
    }
    if(st[id<<1].r >= pos)
        Update(id<<1,pos,k);
    else Update(id<<1|1,pos,k);
    PushUp(id);
}
void Query(int id,int l,int r,int ope)//1是Max 2是Min
{
    if(st[id].l == l && st[id].r == r)
    {
        if(ope == 1)
        {
            Min1 = min(Min1,st[id].Min);
            Max1 = max(Max1,st[id].Max);
        }
        else 
        {
            Min2 = min(Min2,st[id].Min);
            Max2 = max(Max2,st[id].Max);
        }
        return;
    }
    if(st[id<<1].r >= r)
        Query(id<<1,l,r,ope);
    else if(st[id<<1|1].l <= l)
        Query(id<<1|1,l,r,ope);
    else 
    {
        Query(id<<1,l,st[id<<1].r,ope);
        Query(id<<1|1,st[id<<1|1].l,r,ope);
    }
}
void dfs(int u,int fa)
{
    pos[u] = Left[u] = ++cnt;
    pre[u] = fa;
    for(int i = first[u];i != -1;i = nxt[i])
    {
        int v = vv[i];
        if(v == fa) continue;
        dfs(v,u);
    }
    Right[u] = cnt;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
        init();
        for(int i = 1;i < n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            edge[i].from = u;
            edge[i].to = v;
        }
        dfs(1,0);
        for(int i = 1;i <= n;i++)
            key[pos[i]] = a[i];
        buildtree(1,1,n);
        char ope[12];
        while(q--)
        {
            scanf("%s",ope);
            if(ope[0] == 'Q')
            {
                int k;  scanf("%d",&k);
                int u = edge[k].from,v = edge[k].to;
                if(pre[u] == v) swap(u,v);//现在必然是u->v
                int ff = Left[v],tt = Right[v];
                Min1 = inf,Min2 = inf;
                Max1 = -inf,Max2 = -inf;
                Query(1,ff,tt,2);
                if(ff == 1)
                {
                    Query(1,tt+1,cnt,1);
                }
                else if(tt == cnt)
                {
                    Query(1,1,ff-1,1);
                }
                else 
                {
                    Query(1,1,ff-1,1);
                    Query(1,tt+1,cnt,1);
                }
                LL ans = (LL)(((LL)(Min1)) * ((LL)(Max1))) + (LL)(((LL)(Min2)*((LL)(Max2))));
                printf("%lld\n",ans);
            }
            else
            {
                int p,k;    scanf("%d%d",&p,&k);
                Update(1,pos[p],k);
            }
        }
    }
    return 0;
}                          


### 关于L2-050懂蛇语测试点的解析 #### 题目背景 L2-050《懂蛇语》属于中国高校计算机大赛——团队程序设计天梯赛(GDCPC)中的一个题目。该类题目通常涉及字符串处理、模式匹配以及算法优化等内容。虽然具体题面未提供,但从其名称推测,此题可能围绕“蛇语”的翻译或识别展开。 #### 可能的核心考点 基于以往类似的竞赛题目分析[^1],可以推断本题的主要考察方向如下: 1. **字符串处理** 蛇语可能是由特定字符集构成的一种特殊编码形式,选手需通过给定规则将其转换为人类可理解的语言或者验证某串是否符合蛇语定义。 2. **模式匹配与查找** 如果涉及到多条蛇语记录,则需要高效实现子串匹配逻辑来定位目标位置并完成相应操作。这一步骤往往可以通过KMP算法或其他高级数据结构加速执行效率[^2]。 3. **模拟过程** 对某些复杂场景下的行为进行精确描述和重现也是常见命题手法之一,在这里也许会要求按照一定流程逐步演绎整个交流环节直至得出结论为止。 #### 示例解答思路(假设条件) 以下是针对一种假想情况所提供的解决方案框架仅供参考: 假如输入包含若干组样本数据,每组先指定长度n接着列出实际内容s;另外还存在另一参数k代表待查询单词数量q及其列表qs[]. 我们需要判断这些询问项能否完全映射至原始资料里存在的表达方式上. ```python def check_snake_language(n, s, k, qs): result = [] # 构建哈希表存储所有可能出现的形式 snake_dict = set() for i in range(len(s)-len(q)+1): # O(m * n), m=len(q) sub_str = s[i:i+len(q)] if is_valid(sub_str): # 自定义函数检测合法性 snake_dict.add(sub_str) # 查询部分 for q_word in qs: if q_word in snake_dict: result.append("YES") else: result.append("NO") return result if __name__ == "__main__": import sys lines = sys.stdin.readlines() # 假设标准输入已准备好 params = list(map(int,lines[0].split())) string_data = "".join(lines[1:params[0]+1]) queries_count = int(params[-1]) query_words = [line.strip() for line in lines[-queries_count:]] output_results = check_snake_language(*params[:2],query_words=query_words) print("\n".join(output_results)) ``` 以上代码片段仅作为示范用途,并不意味着它适用于任何版本的实际比赛环境之中。真实情况下还需要仔细阅读官方文档说明后再做调整修改。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值