HDU6356:Glad You Came ST表的巧妙利用

首先题意是告诉你要进行m次区间赋最值操作,要求你求出每一个值最后的大小,这题的难点在于查询m的次数是非常多的,高达1e8,所以你想用线段树边修改边查询是不可能的,(因为是随机出的数据,所以有一些剪枝被卡过去了,我女朋友就是这么过的,好气啊!!!)所以这个题用了我觉得很少见的一类数据结构ST表,ST的特征是可以用ologn的时间内建表,然后每次查询都是o(1)的,所以就是很适合这道题的特点了,因为这道题目也是有着多查询,和求最值的,所以我们使用了反着建立ST表的方法去实现这个东西,也是类似于dp的思想,上层是一个区间最大值,但是在dp的过程中,能把取最大值的路径合并一下,并使它的影响依然可以覆盖它的区间,这样逆序建立ST表可以处理区间最大值问题,并快速离线查询。

  待更新:ST表的其他妙用(暂时还没想到这东西除了快速求最值外还有什么用,其实就是快速把可以混淆影响的区间结果以dp的方式传播到下一层吧)

#include<iostream>
#include<cstring>
#include <string>
#include<algorithm>
#include<map>
#include<stack>
#include<queue>
#include <math.h>
#include<vector>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=1e5+20;
const int mod=1e9+7;
typedef unsigned long long ull;
typedef long long ll;
const double pai=acos(-1),eps=1e-8;
int k,len;
unsigned int X,Y,Z;
int st[maxn][20];
unsigned int rng61()
{
    X=X^(X<<11);
    X=X^(X>>4);
    X=X^(X<<5);
    X=X^(X>>14);
    unsigned int W=X^(Y^Z);
    X=Y;
    Y=Z;
    Z=W;
    return Z;
}
int logg[maxn];
int main()
{
    int T=1,num=0;
    for(int i=1;i<maxn;i++)
    {
        if(i<T*2)
            logg[i]=num;
        else{
            T=T*2;
            num++;
            logg[i]=num;
        }
    }
    cin>>T;

    while(T--)
    {

        int n,m;
        scanf("%d%d%d%d%d",&n,&m,&X,&Y,&Z);
//        cin>>n>>m>>X>>Y>>Z;
        for(int i=30;i>=0;i--)
        {
            for(int j=1;j<=n;j++)
                st[j][i]=0;
        }
        for(int i=0;i<m;i++)
        {
            unsigned int a=rng61()%n+1,b=rng61()%n+1,c=rng61()%(1<<30);
            if(a>b)
                swap(a, b);
            int d=logg[(b-a+1)];
            st[a][d]=max(st[a][d],(int)c);
            st[b-(1<<d)+1][d]=max(st[b-(1<<d)+1][d],(int)c);
        }

        for(int i=logg[n+1];i>0;i--)
        {
            for(int j=1;j<=n;j++)
            {

                int j2=j+(1<<(i-1));

                if(j2<=n)
                    st[j2][i-1]=max(st[j2][i-1],st[j][i]);
                st[j][i-1]=max(st[j][i],st[j][i-1]);
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans^=(i*1LL)*st[i][0];
        printf("%lld\n",ans);
    }
}

原文地址:https://www.cnblogs.com/King-of-Dark/p/11626138.html

时间: 2024-08-01 16:39:26

HDU6356:Glad You Came ST表的巧妙利用的相关文章

表驱动法 - 巧妙利用数组返回中文星期

Date对象有个getDay方法,它根据本地时间,返回一个具体日期中一周的第几天.返回值从0~6,分别对应周日~周六 getDay 0 1 2 3 4 5 6 星期几 周日 周一 周二 周三 周四 周五 周六 用到日期相关的需求时需要将getDay返回的值转成星期几,即“这一天”是星期几?比如日历组件中选择日历后返回 “2014-12-22 周一”. 这是一段依然在线上运行的代码 /* * 根据Date对象返回星期几 * @param {Date} date * @return {String}

【BZOJ-4569】萌萌哒 ST表 + 并查集

4569: [Scoi2016]萌萌哒 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 459  Solved: 209[Submit][Status][Discuss] Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2.

ST表超级详解

ST表超级详解 关于ST表,有很多文章,这里本蒟蒻也来发一波~~ 希望能为您提供帮助~~ 1.ST表的介绍 ST表算法全称Sparse-Table算法,是由Tarjan提出的一种解决RMQ问题(区间最值)的强力算法.离线预处理时间复杂度 θ(nlogn),在线查询时间 θ(1),可以说是一种非常高效的算法.不过ST表的应用场合也是有限的,它只能处理静态区间最值,不能维护动态的,也就是说不支持在预处理后对值进行修改.一旦修改,整张表便要重新计算,时间复杂度极高.动态最值可以用线段树.树状数组等来维

RMQ问题 - ST表的简单应用

2017-08-26 22:25:57 writer:pprp 题意很简单,给你一串数字,问你给定区间中最大值减去给定区间中的最小值是多少? 用ST表即可实现 一开始无脑套模板,找了最大值,找了最小值,分别用两个函数实现,实际上十分冗余 所以TLE了 之后改成一个函数中同时处理最大值和最小值,就可以了 AC代码如下: /* @theme:poj 3264 @writer:pprp @declare:ST表(sparse table)稀疏表,用动态规划的思想来解决RMQ问题: @date:2017

[模板]ST表浅析

ST表,稀疏表,用于求解经典的RMQ问题.即区间最值问题. Problem: 给定n个数和q个询问,对于给定的每个询问有l,r,求区间[l,r]的最大值.. Solution: 主要思想是倍增和区间dp. 状态:dp[i][j] 为闭区间[i,i+2^j-1]的最值. 这个状态与转移方程的关系很大,即闭区间的范围涉及到了转移方程的简便性. 转移方程:dp[i][j]=max(dp[i][j-1],dp[i+2^(j-1)][j-1]). 这是显然的,但这里有个细节:第一个项的范围为[i,i+2^

【模板】ST表 洛谷P1816 忠诚

P1816 忠诚 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于 管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了怀疑.于是他决定用一种特别的方法来判断管家的忠诚,他把每次的 账目按1,2,3…编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题. 输入输出格式 输入格式: 输入中第一行有两个数m,n表示有m(m<=100000

GCD(st表)

GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3432    Accepted Submission(s): 1227 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There a

UVA 11475 Extend to Palindrome(后缀数组+ST表)

[题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串. [题解] 用拼接符将原字符串倒序相接,做一遍后缀数组,查询两串相应位置的LCP就是以该点为中心的回文串长度的一半分,奇偶求出所有后缀回文串,保留最长的,则补充部分为剩下的前缀的倒置.至于查询两串的LCP我们可以在height数组建立ST表查询. [代码] #include <cstdio> #

lca最近公共祖先(st表)

大体思路 1.求出每个元素在树中的深度 2.用st表预处理的方法处理出f[i][j],f[i][j]表示元素i上方第2^j行对应的祖先是谁 3.将较深的点向上挪,直到两结点的深度相同 4.深度相同后,祖先可能就在上方,再走几步就到了,于是两个点同时向上移 具体的方法和代码贴在下面 ↓ 具体来看 1.求出每个元素在树中的深度 //求每个节点在树中的深度 void dfs(int pos,int pre)//pre是pos的父节点 { for(int i=0;i<v[pos].size;i++)//