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巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...
随机推荐
- 编程语言-Java-问题整理
jar文件运行报错 - Exception in thread "main" java.lang.UnsupportedClassVersionError 低版本运行高版本文件 ...
- python包的补充
1.包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间 2.常见目录结构 import os 2 os.makedirs('glance/api') 3 os.makedirs('gl ...
- poi小案例
一:pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http: ...
- hive Hsql
show databases; use flume; show tables; desc flume; alter table table_name add columns(dt string); a ...
- spring 配置属性细节
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/qilixiang012/article/details/28233811 概要(红色为上一篇所讲,蓝 ...
- Android关于SurfaceView,SurfaceHolder,SurfaceHolder.CallBack详解
官方的定义: 1.SurfaceView SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface.你可以控制这个Surface的格式和尺寸.Surfacev ...
- Windows程序设计(七)--鼠标
7.2 客户区鼠标消息 当鼠标移过窗口的显示区域时,窗口消息处理程序收到WM_MOUSEMOVE消息.当在窗口的显示区域中按下或者释放一个鼠标按键时,窗口消息处理程序会接收到下面这些消息: 键 按下 ...
- 3. ZooKeeper客户端(一)
ZooKeeper常用客户端有三种:原生客户端.zkClient.curator 项目中使用前,需要导入相关依赖 <dependencies> <dependency> < ...
- XMPP即时通讯协议使用(前传)——协议详解
XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...
- SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换
SpringMVC表单或Json中日期字符串与JavaBean的Date类型的转换 场景一:表单中的日期字符串和JavaBean的Date类型的转换 在使用SpringMVC的时候,经常会遇到表单中的 ...