「THUSCH 2017」大魔法师 解题报告

「THUSCH 2017」大魔法师

狗体面太长,帖链接



思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵,随便搞搞就成了,卡常



Code:

#include <cstdio>
#include <cstring>
namespace io
{
    const int SIZE=(1<<21)+1;
    char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];
    int f,qr;
    // getchar
    #define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    // print the remaining part
    inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    // putchar
    inline void putc(char x){*oS++=x;if(oS==oT)flush();}
    // input a signed integer
    template <class I>
    inline void read(I &x)
    {
        for(f=1,c=gc();c<'0'||c>'9';c=gc()) if(c=='-') f=-1;
        for(x=0;c<='9'&&c>='0';c=gc()) x=x*10+(c&15);x*=f;
    }
    // print a signed integer
    template <class I>
    inline void print(I &x)
    {
        if(!x)putc('0');if(x<0) putc('-'),x=-x;
        while(x)qu[++qr]=x%10+'0',x/=10;
        while(qr)putc(qu[qr--]);
    }
    //no need to call flush at the end manually
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::read;
using io::putc;
using io::print;
const int N=250010;
const int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
#define mul(a,b) ((int)(1ll*(a)*(b)%mod))
struct matrix
{
    int dx[4][4];
    matrix(){memset(dx,0,sizeof dx);}
    matrix friend operator +(matrix a,matrix b)
    {
        for(int i=0;i<=3;i++)
            a.dx[0][i]=add(a.dx[0][i],b.dx[0][i]);
        return a;
    }
    bool friend operator ==(matrix a,matrix b)
    {
        for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
                if(a.dx[i][j]!=b.dx[i][j])
                    return false;
        return true;
    }
}I,t,yuy[N<<2],tag[N<<2];
int n,m;
#define ls id<<1
#define rs id<<1|1
void build(int id,int l,int r)
{
    tag[id]=I;
    if(l==r)
    {
        read(yuy[id].dx[0][0]),read(yuy[id].dx[0][1]),read(yuy[id].dx[0][2]);
        yuy[id].dx[0][3]=1;
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    yuy[id]=yuy[ls]+yuy[rs];
}
void beecute(int id,matrix &a)
{
    matrix bee=matrix();
    for(int i=0;i<=3;i++)
        for(int j=0;j<=3;j++)
            bee.dx[0][i]=add(bee.dx[0][i],mul(yuy[id].dx[0][j],a.dx[j][i]));
    yuy[id]=bee;
    memset(bee.dx,0,sizeof bee.dx);
    for(int i=0;i<=3;i++)
        for(int j=0;j<=3;j++)
        {
            bee.dx[i][j]=add(bee.dx[i][j],mul(tag[id].dx[i][0],a.dx[0][j]));
            bee.dx[i][j]=add(bee.dx[i][j],mul(tag[id].dx[i][1],a.dx[1][j]));
            bee.dx[i][j]=add(bee.dx[i][j],mul(tag[id].dx[i][2],a.dx[2][j]));
            bee.dx[i][j]=add(bee.dx[i][j],mul(tag[id].dx[i][3],a.dx[3][j]));
        }
    tag[id]=bee;
}
void pushdown(int id)
{
    if(tag[id]==I) return;
    beecute(ls,tag[id]);
    beecute(rs,tag[id]);
    tag[id]=I;
}
void change(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R){beecute(id,t);return;}
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) change(ls,L,Mid,l,r);
    else if(l>Mid) change(rs,Mid+1,R,l,r);
    else change(ls,L,Mid,l,Mid),change(rs,Mid+1,R,Mid+1,r);
    yuy[id]=yuy[ls]+yuy[rs];
}
matrix query(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return yuy[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return query(ls,L,Mid,l,r);
    else if(l>Mid) return query(rs,Mid+1,R,l,r);
    else return query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r);
}
int main()
{
    read(n);
    for(int i=0;i<=3;i++) I.dx[i][i]=1;
    build(1,1,n);
    read(m);
    for(int op,l,r,v,i=1;i<=m;i++)
    {
        read(op),read(l),read(r);
        if(op==7)
        {
            t=query(1,1,n,l,r);
            print(t.dx[0][0]);
            putc(' ');
            print(t.dx[0][1]);
            putc(' ');
            print(t.dx[0][2]);
            putc('\n');
            continue;
        }
        t=I;
        if(op==1) t.dx[1][0]=1;
        else if(op==2) t.dx[2][1]=1;
        else if(op==3) t.dx[0][2]=1;
        else if(op==4) read(v),t.dx[3][0]=v;
        else if(op==5) read(v),t.dx[1][1]=v;
        else read(v),t.dx[3][2]=v,t.dx[2][2]=0;
        change(1,1,n,l,r);
    }
    return 0;
}


2019.1.19

原文地址:https://www.cnblogs.com/ppprseter/p/10292922.html

时间: 2024-10-25 17:51:18

「THUSCH 2017」大魔法师 解题报告的相关文章

tyvj P2018 「Nescaf&#233;26」小猫爬山 解题报告

P2018 「Nescafé26」小猫爬山 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Freda和rainbow饲养了N只小猫,这天,小猫们要去爬山.经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<). 描述 Freda和rainbow只好花钱让它们坐索道下山.索道上的缆车最大承重量为W,而N只小猫的重量分别是C1.C2……CN.当然,每辆缆车上的小猫的重量之和不能超过W.每租用一辆缆车,Freda和rainb

「JLOI2015」管道连接 解题报告

「JLOI2015」管道连接 先按照斯坦纳树求一个 然后合并成斯坦纳森林 直接枚举树的集合再dp一下就好了 Code: #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> using std::min; const int N=1<<10; template <class T> void read(T &x) { x=0;cha

「十二省联考 2019」字符串问题 解题报告

「十二省联考 2019」字符串问题 当场就去世了,我这菜人改了一下午 考虑一个A,B之间的连边实际表示了两个A之间的有向边,然后把A的连边处理好,就转成了拓扑排序找环+最长链 但是边数很多,考虑优化连边 A,B之间的连边显然没法优化的,考虑一个B可以表示所有它的后缀A 把串反向建出SAM,然后一个B的后缀就是par树的子树 可以拿倍增定位 好了这题就没了 注意到一个事情,定位的点可能重复,于是对SAM拆点,每个点挂一个vector表示一个A或者B的点在SAM的这个位置 然后考虑如何连边 一个B所

2017 09 17 测验解题报告

预计分数 100+100+20 >=220 实际分数 100+50+20 =170 T1 :100 巧克力棒(chocolate)Time Limit:1000ms Memory Limit:64MB题目描述 LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去.具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后慢慢享用. 它打算每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则 LYK 觉得它完成了一

2017 Multi-University Training 1 解题报告

Add More Zero Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2245    Accepted Submission(s): 1053 Problem Description There is a youngster known for amateur propositions concerning several ma

「csp校内训练 2019-10-24」解题报告

「csp校内训练 2019-10-24」解题报告 T1.猴猴吃苹果 \(Description\) 猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有 \(N \ (N \leq 50000)\) 个苹果,每个苹果有一个编号,分别为 \(0\) ~ \(N - 1\) 它们之间由 \(N-1\) 个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置. 猴猴开始在编号为 \(K \ (K < N)\) 的苹果的位置,并且把这个苹果吃

「csp校内训练 2019-10-30」解题报告

「csp校内训练 2019-10-30」解题报告 T1.树 题目链接(逃) \(Description\): 现在有一棵树,共 \(N\) 个节点. 规定:根节点为 \(1\) 号节点,且每个节点有一个点权. 现在,有 \(M\) 个操作需要在树上完成,每次操作为下列三种之一: \(1 \ x \ a\):操作 \(1\),将节点 \(x\) 点权增加 \(a\). \(2 \ x \ a\):操作 \(2\),将以节点 \(x\) 为根的子树中所有点的权值增加 \(a\). \(3 \ x\)

[LOJ#2331]「清华集训 2017」某位歌姬的故事

[LOJ#2331]「清华集训 2017」某位歌姬的故事 试题描述 IA是一名会唱歌的女孩子. IOI2018就要来了,IA决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符,第iii个音符的音高为 \(h_i\).IA的音域是 \(A\),她只能唱出 \(1\sim A\) 中的正整数音高.因此 \(1\le h_i\le A\). 在写歌之前,IA需要确定下这首歌的结构,于是她写下了 \(Q\) 条限制,其中第 \(i\) 条为:编号在 \(l_i\) 到 \(r_

大數據時代浪潮的「弄潮兒」

進入2015年,海量的數據正在迅速膨脹並變大,它決定著企業的未來發展,雖然現在企業可能並沒有意識到數據爆炸性增長帶來的問題的隱患,但是隨著時間的推移,人們將越來越多的意識到數據對企業的重要性. 面臨海量數據的挑戰 大數據(big data)是時下非常熱門的話題,大數據是用來描述和定義信息爆炸時代產生的海量數據.大數據的發展能夠為人們獲得更為深刻.全面的洞察能力提供前所未有的空間與潛力,那麼如何看待大數據給IT市場帶來的機遇和挑戰呢? 紐約時報網站此前刊載文章稱,大數據時代已經來臨並且正在對每個領