LOJ 2980 「THUSCH 2017」大魔法师——线段树
题目:https://loj.ac/problem/2980
线段树维护矩阵。
然后是 30 分。似乎是被卡常了?……
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define ls Ls[cr]
#define rs Rs[cr]
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=2e5+5e4+,M=5e5+,mod=;
int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;} int n,m,a[N],b[N],c[N],tot,Ls[M],Rs[M];
struct Mtr{
int a[][];
Mtr(){memset(a,,sizeof a);}
void init(){for(int i=;i<;i++)a[i][i]=;}
Mtr operator* (const Mtr &b)const
{
Mtr c;
for(int i=;i<;i++)
for(int k=;k<;k++)
for(int j=;j<;j++)
c.a[i][j]=(c.a[i][j]+(ll)a[i][k]*b.a[k][j])%mod;
return c;
}
Mtr operator+ (const Mtr &b)const
{
Mtr c=*this;
for(int i=;i<;i++)c.a[][i]=upt(c.a[][i]+b.a[][i]);
return c;
}
bool operator== (const Mtr &b)const
{
for(int i=;i<;i++)
for(int j=;j<;j++)if(a[i][j]!=b.a[i][j])return false;
return true;
}
}Ml[],vl[M],tg[M],I,tp;
void build(int l,int r,int cr)
{
if(l==r)
{
vl[cr].a[][]=a[l]; vl[cr].a[][]=b[l];
vl[cr].a[][]=c[l]; vl[cr].a[][]=; return;
}
int mid=l+r>>; tg[cr].init();
ls=++tot; build(l,mid,ls);
rs=++tot; build(mid+,r,rs);
vl[cr]=vl[ls]+vl[rs]; vl[cr].a[][]=r-l+;
}
void init()
{
tot=; build(,n,);
for(int i=;i<=;i++)Ml[i].init();
Ml[].a[][]=; Ml[].a[][]=; Ml[].a[][]=;
I.init();
}
void pshd(int cr)
{
if(tg[cr]==I)return;
tg[ls]=tg[ls]*tg[cr]; tg[rs]=tg[rs]*tg[cr];
vl[ls]=vl[ls]*tg[cr]; vl[rs]=vl[rs]*tg[cr];
tg[cr]=I;
}
void mdfy(int l,int r,int cr,int L,int R,int op,int v)
{
if(l>=L&&r<=R)
{
if(op<=)tp=Ml[op];
if(op==){ tp=I; tp.a[][]=v;}
if(op==){ tp=I; tp.a[][]=v;}
if(op==){ tp=I; tp.a[][]=; tp.a[][]=v;}
tg[cr]=tg[cr]*tp; vl[cr]=vl[cr]*tp; return;
}
int mid=l+r>>; pshd(cr);
if(L<=mid)mdfy(l,mid,ls,L,R,op,v);
if(mid<R)mdfy(mid+,r,rs,L,R,op,v);
vl[cr]=vl[ls]+vl[rs]; vl[cr].a[][]=r-l+;
}
Mtr qry(int l,int r,int cr,int L,int R)
{
if(l>=L&&r<=R)return vl[cr];
int mid=l+r>>; pshd(cr);
if(L>mid)return qry(mid+,r,rs,L,R);
if(R<=mid)return qry(l,mid,ls,L,R);
return qry(l,mid,ls,L,R)+qry(mid+,r,rs,L,R);
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)a[i]=rdn(),b[i]=rdn(),c[i]=rdn();
init(); m=rdn(); int op,l,r,v=;
while(m--)
{
op=rdn();l=rdn();r=rdn();
if(op==)
{
Mtr ans=qry(,n,,l,r);
printf("%d %d %d\n",ans.a[][],ans.a[][],ans.a[][]);
}
if(op>=&&op<=)v=rdn();
if(op<)mdfy(,n,,l,r,op,v);
}
return ;
}
1.行向量乘4*4矩阵,写成 42 而不是 43 的。
2.矩阵乘法的时候,一定要多写很多 if(a[i][k]) 之类的判断。会快一大截!
3.查询的时候,无需返回一个矩阵,可以用全局变量去累计答案。
4.快速输出。
然后还是 95 分……但是把其他 AC 代码交上去,TLE得更严重。这到底是……
UPD(2019.5.18):再交了一次,卡过了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define ls Ls[cr]
#define rs Rs[cr]
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int g[];
void wrt(int x)
{
int t=;
while(x)g[++t]=x%,x/=;
for(int i=t;i;i--)putchar(g[i]+'');
}
const int N=2e5+5e4+,M=5e5+,mod=;
int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;} int n,m,tot,Ls[M],Rs[M],vl[M][],s0,s1,s2,tp[];
bool lz[M];
struct Mtr{
int a[][];
Mtr(){memset(a,,sizeof a);}
void init()
{ for(int i=;i<;i++)a[i][i]=;}
Mtr operator* (const Mtr &b)const
{
Mtr c;
for(int i=;i<;i++)
for(int k=;k<;k++)
if(a[i][k])///
for(int j=;j<;j++)
if(b.a[k][j])
c.a[i][j]=(c.a[i][j]+(ll)a[i][k]*b.a[k][j])%mod;
return c;
}
Mtr operator+ (const Mtr &b)const
{
Mtr c=*this;
for(int i=;i<;i++)c.a[][i]=upt(c.a[][i]+b.a[][i]);
return c;
}
bool operator== (const Mtr &b)const
{
for(int i=;i<;i++)
for(int j=;j<;j++)if(a[i][j]!=b.a[i][j])return false;
return true;
}
}Ml[],tg[M],I,trans;
void Mul(int cr,Mtr b)
{
for(int j=;j<;j++)tp[j]=vl[cr][j],vl[cr][j]=;
tp[]=vl[cr][];
for(int k=;k<;k++)
if(tp[k])
for(int j=;j<;j++)//
if(b.a[k][j])
vl[cr][j]=(vl[cr][j]+(ll)tp[k]*b.a[k][j])%mod;
}
void Plu(int cr,int b)
{
for(int j=;j<;j++)tp[j]=upt(vl[cr][j]+vl[b][j]);
}
void build(int l,int r,int cr)
{
if(l==r)
{
vl[cr][]=rdn(); vl[cr][]=rdn();
vl[cr][]=rdn(); vl[cr][]=; return;
}
int mid=l+r>>; tg[cr].init();
ls=++tot; build(l,mid,ls);
rs=++tot; build(mid+,r,rs);
Plu(ls,rs); for(int j=;j<;j++)vl[cr][j]=tp[j];
vl[cr][]=r-l+;
}
void init()
{
tot=; build(,n,);
for(int i=;i<=;i++)Ml[i].init();
Ml[].a[][]=; Ml[].a[][]=; Ml[].a[][]=;
I.init();
}
void pshd(int cr)
{
if(!lz[cr])return; lz[cr]=;
tg[ls]=tg[ls]*tg[cr]; tg[rs]=tg[rs]*tg[cr];
Mul(ls,tg[cr]); Mul(rs,tg[cr]);//
tg[cr]=I;
lz[ls]=lz[rs]=;
}
void mdfy(int l,int r,int cr,int L,int R)
{
if(l>=L&&r<=R)
{
tg[cr]=tg[cr]*trans; Mul(cr,trans);//
lz[cr]=; return;
}
int mid=l+r>>; pshd(cr);
if(L<=mid)mdfy(l,mid,ls,L,R);
if(mid<R)mdfy(mid+,r,rs,L,R);
Plu(ls,rs); for(int j=;j<;j++)vl[cr][j]=tp[j];
}
void qry(int l,int r,int cr,int L,int R)
{
if(l>=L&&r<=R)
{
s0=upt(s0+vl[cr][]); s1=upt(s1+vl[cr][]);
s2=upt(s2+vl[cr][]); return;
}
int mid=l+r>>; pshd(cr);
if(L<=mid)qry(l,mid,ls,L,R);
if(mid<R)qry(mid+,r,rs,L,R);
}
int main()
{
n=rdn();
init(); m=rdn(); int op,l,r,v=;
while(m--)
{
op=rdn();l=rdn();r=rdn();
if(op==)
{
s0=s1=s2=;
qry(,n,,l,r);
wrt(s0);putchar(' ');
wrt(s1);putchar(' ');
wrt(s2);puts("");
continue;
}
if(op>=&&op<=)
{
v=rdn(); trans=I;
if(op==) trans.a[][]=v;
if(op==) trans.a[][]=v;
if(op==){ trans.a[][]=; trans.a[][]=v;}
}
else trans=Ml[op];
if(op<)mdfy(,n,,l,r);
}
return ;
}
LOJ 2980 「THUSCH 2017」大魔法师——线段树的更多相关文章
- 「THUSCH 2017」大魔法师 解题报告
「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...
- 「THUSCH 2017」大魔法师
Description 大魔法师小 L 制作了 \(n\) 个魔力水晶球,每个水晶球有水.火.土三个属性的能量值.小 L 把这 \(n\) 个水晶球在地上从前向后排成一行,然后开始今天的魔法表演. 我 ...
- LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)
题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...
- LOJ 2979 「THUSCH 2017」换桌——多路增广费用流
题目:https://loj.ac/problem/2979 原来的思路: 优化连边.一看就是同一个桌子相邻座位之间连边.相邻桌子对应座位之间连边. 每个座位向它所属的桌子连边.然后每个人建一个点,向 ...
- @loj - 2977@ 「THUSCH 2017」巧克力
目录 @description@ @solution@ @accepted code@ @details@ @description@ 「人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道.」 明 ...
- LOJ #2978「THUSCH 2017」杜老师
听说LOJ传了THUSC题赶紧上去看一波 随便点了一题都不会做想了好久才会写暴力爆了一发过了... LOJ #2978 题意 $ T$次询问,每次询问$ L,R$,问有多少种选取区间中数的方案使得选出 ...
- LOJ 2978 「THUSCH 2017」杜老师——bitset+线性基+结论
题目:https://loj.ac/problem/2978 题解:https://www.cnblogs.com/Paul-Guderian/p/10248782.html 第 i 个数的 bits ...
- LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树
题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...
- loj#2978. 「THUSCH 2017」杜老师(乱搞)
题面 传送门 题解 感谢yx巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...
随机推荐
- Linux_Bash脚本基础
目录 目录 Bash使用基础 if 语句 运算符 逻辑表达式 不将执行指令的结果显示出来 echo 语句 从Bash接受输入参数 Case语句 循环 for 语句 While语句 内置变量和函数 AW ...
- c#处理json格式类型的字符串
string channelGroup=[{"SpType":"1","BaseInfoId":["xxx"," ...
- Dp状态设计与方程总结
1.不完全状态记录<1>青蛙过河问题<2>利用区间dp 2.背包类问题<1> 0-1背包,经典问题<2>无限背包,经典问题<3>判定性背包问 ...
- KMP字符串匹配学习
KMP字符串匹配学习 牛逼啊 SYC大佬的博客
- hdu4734 F(x)(数位dp)
题目传送门 F(x) Time Limit: 1000/500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- easyui datagrid数据网格
EasyUI是一组基于jQuery的UI插件集合,它的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.它的许多控件让我们不必写很复杂的javascript,从而极大地提高了开发效率. ...
- JavaScript—— 案例:表单验证
QQ号:<input type="text" id="txtQQ"><span></span><br> 邮箱:& ...
- photoshop中调整图层的颜色深浅明暗
图像-调整-可选颜色, 选中某一个颜色如绿色,可以将绿色调的深一点或浅一点
- ssh-agent - 认证代理
总览 (SYNOPSIS) ssh-agent [-a bind_address ] [-c | -s ] [-t life ] [-d ] [command [args ... ] ] ssh-ag ...
- CentOS7.6系统安装zabbix3.4.8客户端
一. 准备安装包 将本地的zabbix-3.4.8软件包上传至服务器, 二. 安装依赖包 安装依赖包:yum install gcc* pcre* psmisc -y 三. 安 ...