首页 > 其他分享 >省赛线段树存档

省赛线段树存档

时间:2022-10-02 21:12:20浏览次数:60  
标签:int 存档 ll tr mid tl 100010 省赛 线段

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read()
{
    int x;scanf("%d",&x);return x;
}
ll mod=998244353ll,ans;
ll inv[100010],fac[100010];
ll quick(ll a,ll b)
{
    ll t=1;
    while(b)
    {
        if(b&1)
            t=t*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return t;
}
ll C(ll n,ll m)
{
    return fac[m]*inv[n]%mod*inv[m-n]%mod;
}
int c[100010*4][4][4],lazy[400010],xx,yy;
int a[100010],t[4][4],tl[4][4],tr[4][4],lp[400010],rp[400010];
char s[100010];

void build(int x,int l,int r)
{
    if(l==r){
        lp[x]=rp[x]=a[l];
        return ;
    }
    int mid=(l+r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            c[x][i][j]=c[x*2][i][j]+c[x*2+1][i][j];
    c[x][a[mid]][a[mid+1]]++;
    lp[x]=lp[x*2];
    rp[x]=rp[x*2+1];
}
void pushdown(int x,int l,int r)
{
    if(lazy[x]==0)
        return ;
    lazy[l]=(lazy[l]+lazy[x])%4;
    lazy[r]=(lazy[r]+lazy[x])%4;
    lp[l]=(lp[l]+lazy[x])%4;
    rp[l]=(rp[l]+lazy[x])%4;
    lp[r]=(lp[r]+lazy[x])%4;
    rp[r]=(rp[r]+lazy[x])%4;
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        {
            tl[i][j]=c[l][i][j];
            tr[i][j]=c[r][i][j];
        }
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        {
            c[l][(i+lazy[x])%4][(j+lazy[x])%4]=tl[i][j];
            c[r][(i+lazy[x])%4][(j+lazy[x])%4]=tr[i][j];
        }
}
void add(int x,int l,int r,int tl,int tr)
{
    if(tl<=l&&r<=tr)
    {
        lazy[x]=(lazy[x]+1)%4;
        if(l==r)
        {
            rp[x]=lp[x]=(lp[x]+1)%4;
        }
        else
        {
            lp[x]=(lp[x]+1)%4;
            rp[x]=(rp[x]+1)%4;
        }
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                t[i][j]=c[x][i][j];
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                c[x][(i+1)%4][(j+1)%4]=t[i][j];
        return ;
    }
    if(lazy[x])
        pushdown(x,x*2,x*2+1);
    int mid=(l+r)/2;
    if(tr<=mid)
        add(x*2,l,mid,tl,tr);
    else if(tl>mid)
        add(x*2+1,mid+1,r,tl,tr);
    else
    {
        add(x*2,l,mid,tl,tr);
        add(x*2+1,mid+1,r,tl,tr);
    }
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            c[x][i][j]=c[x*2][i][j]+c[x*2+1][i][j];
    c[x][rp[x*2]][lp[x*2+1]]++;
    lp[x]=lp[x*2];
    rp[x]=rp[x*2+1];
}
void ask(int x,int l,int r,int tl,int tr)
{
    if(tl<=l&&r<=tr)
    {
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                t[i][j]+=c[x][i][j];
        return ;
    }
    if(lazy[x])pushdown(x,x*2,x*2+1);
    int mid=(l+r)/2;
    if(tr<=mid)
        ask(x*2,l,mid,tl,tr);
    else if(tl>mid)
        ask(x*2+1,mid+1,r,tl,tr);
    else
    {
        ask(x*2,l,mid,tl,tr);
        ask(x*2+1,mid+1,r,tl,tr);
        t[rp[x*2]][lp[x*2+1]]++;
    }
}
int main()
{
//     freopen("1.in","r",stdin);
    fac[0]=1;
    for(int i=1;i<=100000;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[100000]=quick(fac[100000],mod-2);
    for(int i=99999;~i;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
    int n=read();int q=read();
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
        a[i]=s[i]-'A';
    build(1,1,n);    
    int l,r,k;
    for(int i=1;i<=q;i++)
    {
        if(read()&1)
        {
            l=read();r=read();
            add(1,1,n,l,r);
        }
        else
        {
            l=read();r=read();k=read();
            if(l==r)
            {
                printf("1\n");
                continue;
            }
            for(int ii=0;ii<4;ii++)
                for(int j=0;j<4;j++)
                    t[ii][j]=0;
            ask(1,1,n,l,r);//Áît±ä³ÉÇø¼äÀïÊýÁ¿
            int fuyi=1;
            for(int ii=0;ii<4;ii++)
                for(int j=0;j<=ii;j++)
                    fuyi+=t[ii][j];
            if(fuyi>k)
                printf("%lld\n",0ll);
            else 
                printf("%lld\n",C(k-fuyi,r-l+1-fuyi));
        }
    }
    // cout<<ans;
}

 

标签:int,存档,ll,tr,mid,tl,100010,省赛,线段
From: https://www.cnblogs.com/qywyt/p/16749469.html

相关文章

  • 线段树的简单扩展及应用
    线段树的简单扩展及应用参考:线段树的高级用法-Alex_Wei注:这篇文章只开了个头就鸽了,如果真的准备学到点什么的话可以直接点上面这篇文章(前言线段树作为一种有效维护区......
  • PADS应用笔记:Layout隐藏线段方框和叉号
    问题用layout看图纸时方框和叉号太影响观感了,如何隐藏方法方框叉号......
  • 代码模板存档
    代码模板存档)2022.9.30增加并查集、埃氏筛、线性筛、快速幂、扩展欧几里得、求逆元一般C++比赛文件模板#include<bits/stdc++.h>usingi64=longlong;intm......
  • 线段树学习笔记(入门)
    目录前言线段树基础2.1定义2.2区间操作和懒标记2.3一些例题1.前言应老师要求,来写一篇关于线段树的学习笔记2.线段树基础2.1定义线段树是一种二叉搜索树,与......
  • 需要对某些区间递归处理的线段树的维护
    这篇总结来源于本蒟蒻打了两道题目发现了这种类型题,却不知道怎么给它起名字......对一些已经看出来对区间进行操作和维护,但pushup操作不太容易想出来的题目来说,我们不妨尝......
  • AcWing 算法提高课 线段树+扫描线法 求矩形之并的面积
    例题:求解多个长方形之并的面积https://www.acwing.com/problem/content/249/蓝色表示长方形,红色表示扫描线如下图所示,对于每一个横向的区间,在纵向维护线段树根据纵向......
  • 【luogu CF1109E】Sasha and a Very Easy Test(线段树)
    SashaandaVeryEasyTest题目链接:luoguCF1109E题目大意维护一个长度为n的序列,有区间乘,单点除(保证能整除),区间求和答案对p取模。p不一定是质数。思路麻了考场......
  • 两个和最大的区间(线段树+单调栈+dp)
      胜哥投喂的一道面试题  题意:有一个环形数组\(a\),找出两个不重叠的子串,是的这两个区间内所有的数加起来的和最大。  数据范围:\(1\leqn\leq10^5,\left|......
  • 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解
    什么是线段树线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值、区间和等问题。线段树的用处对编号连续的一些点进行修改或者统计操作,修改和统计的复杂......
  • mex(权值线段树+线段树上二分)
      思路:首先看到区间维护,想到线段树,但是很明显无法用线段树直接维护区间最小没出现过的自然数,因为假若一个节点的左右儿子节点的值都为0,我们是无法推断出父节点的值是几......