首页 > 其他分享 >线段树水题

线段树水题

时间:2023-05-17 14:22:22浏览次数:32  
标签:dist int 线段 树水题 times 区间 id

[THUSCH2017] 大魔法师

​ 给定 \(n\) 个三元组 \((A,B,C)\) 。共有 \(m\) 种区间操作,分为三大类,七小类。

1.\(A_i=A_i+B_i\) 2.\(B_i=B_i+C_i\) 3.\(C_i=C_i+A_i\)

给定值 \(v\) 4. \(A_i=A_i+v\) 5. \(B_i=B_i\times v\) 6. \(C_i=v\)

7.区间查询所有三元组的和对 \(998244353\) 取模的结果。

​ \(n,m\le 2.5\times10^5\)


直接建立线段树,每个节点上改为维护矩阵。将六种修改操作分别建出转移矩阵即可,需要支持区间乘法。卡常可以使用矩阵乘法循环展开和取模优化。

[NOI2016] 区间

​ 给定 \(n\) 个区间,要从中选出 \(m\) 个区间,使得它们共同包含至少一个位置。对于一个选取方案,其花费为选中的最长区间长度减去最短区间长度。求最小权值,若不存在合法方案输出 \(-1\) 。

​ \(n\le 5\times 10^5\;\;m\le 2\times 10^5\;\;0\le l\le r\le 10^9\)


我们可以先对区间长度排个序。然后我们依次将区间加入,利用双指针,如果存在某个位置出现次数大于等于 \(m\) ,我们再不断删去区间,同时不断更新答案。然后我们考虑如何去判断某个位置出现次数大于等于 \(m\) ,我们先将所有区间离散化,然后扔到一棵线段树上,记录区间最大值,维护区间加的操作即可。时间复杂度为 \(O(n\log n)\) 。

[HEOI2013] Segment

[JSOI2008] Blue Mary 开公司

​ \(n\) 个操作,包括:加入一条两端点为点 \((x_0,y_0),(x_1,y_1)\) 的线段,询问当 \(x=k\) 时纵坐标最大的那个线段的编号。强制在线。

​ \(n\le 10^5\)


李超线段树模板题。我们维护区间中的最优线段,我们取当 \(x=mid\) 时值更大的线段为该区间的最优线段,然后我们通过比较 \(l\) 处和 \(r\) 处的值大小,递归地去更新左右区间。注意李超线段树不存在 \(pushup\) 和 \(pushdown\) 等操作。询问的时候直接在树上递归取区间最大值即可,注意一定要递归去取最大值。时间复杂度为 \(O(n\log ^2n)\) 。

以下代码以 [HEOI2013] Segment 为例。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+9,mod=39989,mod2=1e9,INF=2e9;
const double eps=1e-10;
typedef long long int ll;
typedef pair <double,int> PDI;
struct seg{
    double k,b;
    int l,r;
} p[N];
struct node{
    int maxx;
} tr[N<<2];
int n,last,tot;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0' && c<='9') {x=x*10+c-48,c=getchar();}
    return x*f;
}
inline double get(int id,int x)
{
    if(x<p[id].l || x>p[id].r) return -INF;//不在区间内
    return p[id].k*x+p[id].b;
}
void upd(int k,int l,int r,int L,int R,int id)
{
    if(R<l || r<L) return;
    if(L<=l && r<=R)
    {
        if(tr[k].maxx==0)
        {
            tr[k].maxx=id;
            return;
        }
        int mid=(l+r)>>1;
        if(get(id,mid)-get(tr[k].maxx,mid)>eps) swap(id,tr[k].maxx);//mid处值较大的作为区间代表
        if((get(id,l)-get(tr[k].maxx,l)>eps) || (get(id,l)==get(tr[k].maxx,l) && id<tr[k].maxx)) upd(k<<1,l,mid,L,R,id);
        if((get(id,r)-get(tr[k].maxx,r)>eps) || (get(id,r)==get(tr[k].maxx,r) && id<tr[k].maxx)) upd(k<<1|1,mid+1,r,L,R,id);
        return;
    }
    int mid=(l+r)>>1;
    upd(k<<1,l,mid,L,R,id),upd(k<<1|1,mid+1,r,L,R,id);
}
PDI maxx(PDI a,PDI b)
{
    if(a.first-b.first>eps) return a;
    else if(b.first-a.first>eps) return b;
    else if(a.second<b.second) return a;
    return b;
}
PDI query(int k,int l,int r,int pos)
{
    PDI ans;
    if(tr[k].maxx!=0) ans={get(tr[k].maxx,pos),tr[k].maxx};
    if(l==r) return ans;
    int mid=(l+r)>>1;
    if(pos<=mid) ans=maxx(ans,query(k<<1,l,mid,pos));
    else ans=maxx(ans,query(k<<1|1,mid+1,r,pos));
    return ans;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        int opt=read();
        if(opt==0)
        {
            int k=read();
            k=(k+last-1)%mod+1;
            last=query(1,1,mod,k).second;
            printf("%d\n",last);
        }
        else
        {
            int x0=read(),y0=read(),x1=read(),y1=read();
            x0=(x0+last-1)%mod+1,x1=(x1+last-1)%mod+1,y0=(y0+last-1)%mod2+1,y1=(y1+last-1)%mod2+1;
            ++tot;
            if(x0==x1)
                p[tot].k=0,p[tot].b=max(y0,y1),p[tot].l=p[tot].r=x0;
            else
            {
                p[tot].k=(y1-y0)*1.0/(x1-x0);
                p[tot].b=y0-p[tot].k*x0;
                p[tot].l=min(x0,x1),p[tot].r=max(x0,x1);
            }
            upd(1,1,mod,min(x0,x1),max(x0,x1),tot);
        }
    }
    return 0;
}

[SDOI2016]游戏

​ 给定一棵 \(n\) 个点的带边权树。每个节点上有若干个数字,初始每个节点上为正无穷。有 \(Q\) 次操作,一是在 \(s\) 到 \(t\) 路径上的所有点 \(u\) 上添加一个值为 \(a\times dist_{u,s}+b\) 的数字,二是查询 \(s\) 到 \(t\) 路径上所有点上的数字的最小值。

​ \(n\le 10^5\;\;Q\le 10^5\)


我们对 \(a\times dist_{u,s}+b\) 这个式子进行一个拆解。令 \(LCA(s,t)=p\) ,\(dist_i\) 表示从根节点到点 \(i\) 的距离。则在 \(s\) 到 \(p\) 路径上的所有点 \(i\) ,插入了值

\[a\times (dist_s-dist_i)+b=-a\times dist_i+a\times dist_s+b \]

在 \(p\) 到 \(t\) 路径上的所有点 \(i\) ,插入了值

\[a\times(dist_i+dist_s-2\times dist_p)+b=a\times dist_i+a\times (dist_s-dist_p)+b \]

发现就是加了两条线段,所以我们用李超线段树去维护,同时还要维护一个区间最小值。而对于树上路径我们直接用树剖处理即可。时间复杂度为 \(O(n\log ^3n )\) 。

标签:dist,int,线段,树水题,times,区间,id
From: https://www.cnblogs.com/LYT0122/p/17408611.html

相关文章

  • Codeforces Round 767 (Div. 1) E. Groceries in Meteor Town (Kruskal重构树 + 线段
    传送门  出现最大路径权值就应该联想到克鲁斯卡尔重构树,我们对于克鲁斯卡尔重构树求一遍dfs序,维护所有白色点的最大最小dfn(包括出发点),求出最大最小dfn的最近公共祖先既是答案。注意需要特判一下除了本身以外没有白色点情况。#include<bits/stdc++.h>intn,m;constintN......
  • 可持续化线段树
    可持续化线段树前言:“这个数据结构是属于比较抽象的一类。并且代码实现比较繁琐复杂。”别人都这么说,我却觉得挺好理解、也挺好写的(可能是因为我曾经与多道线段树毒瘤题抗争多次)。为了避免以后我突然脑子抽了不记得了,可以拿出来看看。所以写下这篇笔记,希望也能帮到大家。建......
  • P3919 【模板】可持久化线段树 1(可持久化数组) 题解
    一、题目描述:维护这样的一个长度为$n$的数组,支持以下两种操作$1$:在某个历史版本上修改某一个位置上的值$2$:访问某个历史版本上的某一位置的值每进行一次操作,就会生成一个新的版本(对于操作2,生成的就是一个完全一样的版本)。版本编号即为当前操作......
  • 线段树选记
    1.[TJOI2018]数学计算题目描述小豆现在有一个数\(x\),初始值为\(1\)。小豆有\(Q\)次操作,操作有两种类型:1m:将\(x\)变为\(x\timesm\),并输出\(x\bmodM\)2pos:将\(x\)变为\(x\)除以第\(pos\)次操作所乘的数(保证第\(pos\)次操作一定为类型1,对于每一个类型1......
  • hdu:LCIS(线段树+区间合并)
    ProblemDescriptionGivennintegers.Youhavetwooperations:UAB:replacetheAthnumberbyB.(indexcountingfrom0)QAB:outputthelengthofthelongestconsecutiveincreasingsubsequence(LCIS)in[a,b].InputTinthefirstline,indicatingt......
  • 线段树合并 学习笔记
    算法两棵动态开点线段树,直接把一棵线段树上的信息合并到另一棵树上。递归合并:如果某个节点两棵都有,合并,然后递归下去。否则直接返回节点。复杂度证明记权值线段树值域范围为\(m\),\(n\)次插入操作。因为动态开点,一次插入会新增\(\log_2m\)个节点,总节点数\(n\ti......
  • 线段树
    线段树--解决区间问题的数据结构,相比于树状数组,更具有普适性;完全二叉树的性质:根节下标为1,,节点为i的节点,左子节点为2*i,右子节点为2*i+1;代表nums中单个元素的节点tree[x]应当在树的最底层,即叶子节点;更大的区间从叶子节点开始向上构成;代表区间【L,R】的节点tree【i】,左子节点tre......
  • 「学习笔记」可持久化线段树
    可持久化数据结构(Persistentdatastructure)总是可以保留每一个历史版本,并且支持操作的不可变特性(immutable)。主席树全称是可持久化权值线段树,给定\(n\)个整数构成的序列\(a\),将对于指定的闭区间\(\left[l,r\right]\)查询其区间内的第\(k\)小值。可持久化线段......
  • Chemistry Experiment Codeforces Round 247 (Div. 2) 线段树动态开点,二分
    第一次写的时候还不会线段树的动态开点,写了一个是线段树但是是\(O(N^2)\)的写法,现在用动态开点武装了自己,会了正解\(O(qlogn^2)\)。首先建立一个权值线段树,但这里的权值很大,通过动态开点去建树来节省空间,对于两种操作:操作1,常见的动态开点的单点修改操作2,二分答案,然后在线段树......
  • 吉老师线段树学习笔记(内含吉老师ppt)
    Segmenttreebeats吉老师线段树SegmenttreeBeats!.pdf_免费高速下载|百度网盘-分享无限制(baidu.com)为广大oier们提供学习ppt(笑)历史最大值未完工作用用于维护区间最值和区间历史最值的线段树区间最值引入问题给定一个长度为n的数列A,有m次操作:1.将区间\([l,r]\)里......