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巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...
随机推荐
- 给url添加时间戳,解决浏览器缓存
//解决浏览器缓存function timestamp(url){ // var getTimestamp=Math.random(); var getTimestamp=new Date().get ...
- Excelvba从另一个工作簿取值
Private Sub getValue_Click() Dim MyWorkbook As Workbook Set MyWorkbook = Application.Workbooks.Open( ...
- 用php实现一个简单的爬虫,抓取电影网站的视频下载地址
昨天没什么事,先看一下电影,就用php写了一个爬虫在视频网站上进行视频下载地址的抓取,这里总结一下抓取过程中遇到的问题 1:通过访问浏览器来执行php脚本这种访问方式其实并不适合用来爬网页,因为要受到 ...
- P4126 [AHOI2009]最小割(网络流+tarjan)
P4126 [AHOI2009]最小割 边$(x,y)$是可行流的条件: 1.满流:2.残量网络中$x,y$不连通 边$(x,y)$是必须流的条件: 1.满流:2.残量网络中$x,S$与$y,T$分别 ...
- SQL server 聚集索引与主键的区别
主键是一个约束(constraint),他依附在一个索引上,这个索引可以是聚集索引,也可以是非聚集索引. 所以在一个(或一组)字段上有主键,只能说明他上面有个索引,但不一定就是聚集索引. 例如下面: ...
- 【问题解决方案】在某个文件夹下打开命令提示符或Git Bash
参考链接: 百度知道:怎么在某个文件夹下打开命令提示符 问题: 当文件夹比较深时,一直cd进入文件夹内部就显得非常迟缓了. 解决: cmd:打开所需文件夹路径后,在上面的路径显示框中输入CMD,然后回 ...
- vue iview分页
距离上次博客更新已经快一个月了,期间也有想法在空闲的时候更新几篇博文. 燃鹅,最近懒癌作祟,丢掉的东西越来越多,再不遏止的话就真成癌了. 趁着刚看完一篇心灵鸡汤,让打满鸡血的我总结下前段时间用到的iv ...
- C#实现百度ping功能
网站优化必做的事情之一,百度ping,主动推送给百度 文章添加时调用百度推送方法 //保存 protected void btnSubmit_Click(object sender, EventArg ...
- 函数异步模拟实现ajax
//模拟ajax function getData(callback){ setTimeout(function(){ var name='leo' callback(name) },1000) re ...
- worldcloud库的使用
worldcloud库的使用 worldcloud是一个优秀的第三方词云展示库,用来实现比较有逼格的数据可视化效果.更加直观与艺术的展示单词. worldcloud对象的创建 worldcloud.W ...