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巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...
随机推荐
- Red Hat Linux下安装JDK
1. 下载Linux平台的JDK 下载对应操作系统的jdk,操作系统是32位的就下32位的jdk,64位的就下64位的jdk.下错了装不上的. 下载地址:http://www.Oracle.com/t ...
- 测开之路七十一:监控平台之js
监控平台的js //datetimepicker的初始化函数(主要是对选择时间的下拉框)function init_datetimepicker() { //初始化格式和规则 $('#start'). ...
- Kubernetes tutorial - K8S 官方入门教程 中文翻译
官方教程,共 6 个小节.每一小节的第一部分是知识讲解,第二部分是在线测试环境的入口. kubectl 的命令手册 原文地址 1 创建集群 1.1 使用 Minikube 创建集群 Kubernete ...
- Picture【HDU - 1828】【扫描线】
题目链接 这道题求的是这些可能存在重叠的小方块可能构成的合成方块的周长的值是多少,有简单却会很复杂的做法就是去跑纵向和横向两次的扫描线,求得最后的两个周长和,但是这样的做法未免显得复杂了,我们完全可以 ...
- 腾达Tenda W311MA无线网卡Linux下驱动安装
菜鸟看这里https://help.ubuntu.com/community/WifiD ... enda_W311M 最近也买了颗Tenda W311M网卡,简单说一下驱动的安装和hostapd做S ...
- 3.创建线程的第二种写法,继承threading.Tread类,重写run方法
#创建线程的第二种写法 #1.自定义一个类 #2.继承Thread #3.重写run()方法 import threading,time,random class MyThread(threading ...
- 身份证验证的js
function isIdCardNo(num) { num = num.toUpperCase(); //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能 ...
- Mybatis开发中前端控制器注解@Controller 引用的类错误
import org.springframework.web.portlet.ModelAndView; 错误 import org.springframework.web.servlet.Model ...
- spring-第十八篇之spring AOP基于XML配置文件的管理方式
1.在XML配置文件中配置切面.切入点.增强处理.spring-1.5之前只能使用XML Schema方式配置切面.切入点.增强处理. spring配置文件中,所有的切面.切入点.增强处理都必须定义在 ...
- [poj3074]Sudoku(舞蹈链)
题目链接:http://poj.org/problem?id=3074 舞蹈链精确覆盖的经典题目,一个数独每个位置的要求,可以得到以下四个约束1.每个位置有且只有一个数字2.每个位置的数字在一行只能出 ...