BZOJ 4085 丧心病狂的毒瘤题目 线段树+矩乘
思路:
一眼矩阵快速幂 再用线段树维护一下矩阵就完了...
我hhhhh 哎我还是too young,too simple 入了这个大坑
线段树维护9个值

以上
如果A+1 转移矩阵是这个样子的

B+1

A-1 B-1 同理行么.....
写了一晚上+一上午 调完了
发现自己被卡常?
我了个大曹
我们发现一开始的矩阵最后一行不变
矩乘的时候特判一发 还是过不去
预处理2^k的矩阵
快速幂的时候省一倍常数 加个快读
80432 ms
卡过去了!!
//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int mod=,N=;
int n,q,a,b,A[N],F[N],d[N][],lazy[N*][];
inline int read(){
int x=;char p=getchar();
while(p<''||p>'')p=getchar();
while(p>=''&&p<='')x=x*+p-'',p=getchar();
return x;
}
struct MATRIX{
int a[][];
void init(){memset(a,,sizeof(a));}
}t[],t0;
int pow(int x,int y){
int res=;
while(y){
if(y&)res=1ll*res*x%mod;
x=1ll*x*x%mod,y>>=;
}return res;
}
MATRIX operator*(MATRIX &a,MATRIX &b){
static MATRIX c;c.init();
for(int i=;i<;i++)
for(int j=;j<;j++){
for(int k=;k<;k++)
c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%mod;
}
c.a[][]=;
return c;
}
MATRIX power(int k){
static MATRIX res;res.init();
res.a[][]=res.a[][]=res.a[][]=;
for(int i=;k;k>>=,i++)if(k&)res=res*t[i];
return res;
}
struct Matrix{
int m[][];
void init(){memset(m,,sizeof(m));}
void init1(){
int B[][]={
{,,,,,,,,},
{,,,,,,,,},
{a,,,,,,b,,},
{,a,,,,,,b,},
{,,,,,,,,},
{,,,,a,,,,b},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
};
memcpy(m,B,sizeof(B));
}
void init2(){
int B[][]={
{,,,,,,,,},
{a,,,,b,,,,},
{,,,,,,,,},
{,,a,,,b,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,a,,b},
{,,,,,,,,},
};
memcpy(m,B,sizeof(B));
}
void init3(){
int x,y,z;
if(a){
int inv=pow(a,mod-);
x=inv,y=mod-inv,z=1ll*b*(mod-inv)%mod;
}
else x=,y=,z=mod-b;
int B[][]={
{y,,x,,,,z,,},
{,y,,x,,,,z,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,y,x,,,z},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
};
memcpy(m,B,sizeof(B));
}
void init4(){
int x,y,z;
if(a){
int inv=pow(a,mod-);
x=inv,y=mod-inv,z=1ll*b*(mod-inv)%mod;
}
else x=,y=,z=mod-b;
int B[][]={
{y,x,,,z,,,,},
{,,,,,,,,},
{,,y,x,,z,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,,,},
{,,,,,,y,x,z},
{,,,,,,,,},
{,,,,,,,,},
};
memcpy(m,B,sizeof(B));
}
}cng[][],I;
Matrix operator*(Matrix &a,Matrix &b){
Matrix c;c.init();
for(int i=;i<;i++)
for(int j=;j<;j++){
for(int k=;k<;k++)
c.m[i][j]=(c.m[i][j]+1ll*a.m[i][k]*b.m[k][j])%mod;
}
return c;
}
void bz(){
cng[][].init1();cng[][].init2();
cng[][].init3();cng[][].init4();
for(int i=;i<;i++){
cng[i][]=I;
for(int j=;j<=;j++)
cng[i][j]=cng[i][j-]*cng[i][j-];
}
}
struct Line{
int m[];
void set(int aa_1,int aa,int bb_1,int bb){
m[]=1ll*aa_1*bb_1%mod,m[]=1ll*aa_1*bb%mod,m[]=1ll*aa*bb_1%mod,
m[]=1ll*aa*bb%mod,m[]=aa_1,m[]=aa,m[]=bb_1,m[]=bb,m[]=;
}
}tr[<<],ans;
Line operator+(Line &a,Line &b){
Line c;
for(int i=;i<;i++)c.m[i]=(a.m[i]+b.m[i])%mod;
return c;
}
Line operator*(Matrix &a,Line &b){
Line c;memset(c.m,,sizeof(c.m));
for(int i=;i<;i++)
for(int j=;j<;j++)
c.m[i]=(c.m[i]+1ll*a.m[i][j]*b.m[j])%mod;
return c;
}
void change(Line &f,Matrix r[],int k){
for(int i=;k;k>>=,i++)if(k&)f=r[i]*f;
}
void calc(int pos,int a0,int a1){
if(a0){
if(a0<)change(tr[pos],cng[],-a0);
else change(tr[pos],cng[],a0);
}
if(a1){
if(a1<)change(tr[pos],cng[],-a1);
else change(tr[pos],cng[],a1);
}
}
void push_down(int pos,int l,int r){
calc(pos,lazy[pos][],lazy[pos][]);
if(l<r){
int lson=pos<<,rson=pos<<|;
lazy[lson][]+=lazy[pos][],lazy[lson][]+=lazy[pos][];
lazy[rson][]+=lazy[pos][],lazy[rson][]+=lazy[pos][];
}
lazy[pos][]=lazy[pos][]=;
}
void push_up(int pos,int l,int r){
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
push_down(lson,l,mid),push_down(rson,mid+,r);
tr[pos]=tr[lson]+tr[rson];
}
void build(int l,int r,int pos){
if(l==r){
tr[pos].set(d[l-][],d[l-][],d[r+][],d[r+][]);
return;
}
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
build(l,mid,lson),build(mid+,r,rson);
push_up(pos,l,r);
}
void insert(int l,int r,int pos,int L,int R,int op){
if(L>R)return;
if(l>=L&&r<=R){
if(!op)lazy[pos][]++;
else if(op==)lazy[pos][]++;
else if(op==)lazy[pos][]--;
else if(op==)lazy[pos][]--;
return;
}push_down(pos,l,r);
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<L)insert(mid+,r,rson,L,R,op);
else if(mid>=R)insert(l,mid,lson,L,R,op);
else insert(l,mid,lson,L,R,op),insert(mid+,r,rson,L,R,op);
push_up(pos,l,r);
}
void query(int l,int r,int pos,int L,int R){
if(L>R)return;
push_down(pos,l,r);
if(l>=L&&r<=R){ans=ans+tr[pos];return;}
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<L)query(mid+,r,rson,L,R);
else if(mid>=R)query(l,mid,lson,L,R);
else query(l,mid,lson,L,R),query(mid+,r,rson,L,R);
}
signed main(){
scanf("%d%d%d%d",&n,&q,&a,&b);
for(int i=;i<;i++)I.m[i][i]=;
t[].a[][]=t[].a[][]=t[].a[][]=,t[].a[][]=a,t[].a[][]=b;
t0.a[][]=t0.a[][]=,t0.a[][]=;
for(int i=;i<=;i++)t[i]=t[i-]*t[i-];
for(int i=;i<=n;i++){
A[i]=read();
if(A[i]!=){
MATRIX temp=power(A[i]-);temp=temp*t0;
d[i][]=temp.a[][],d[i][]=temp.a[][];
}
else d[i][]=,d[i][]=;
d[i][]=(d[i][]+1ll*d[i][]*a+b)%mod;
d[i][]=(d[i][]+1ll*d[i][]*a+b)%mod;
}bz(),build(,n-,);
while(q--){
char op[];int l,r;
scanf("%s%d%d",op,&l,&r);
if(op[]=='q'){
memset(ans.m,,sizeof(ans.m));
query(,n-,,l+,r-);
printf("%d\n",ans.m[]);
}
else if(op[]=='p')insert(,n-,,l+,min(n-,r+),),insert(,n-,,max(l-,),r-,);
else insert(,n-,,l+,min(n-,r+),),insert(,n-,,max(l-,),r-,);
}
}
BZOJ 4085 丧心病狂的毒瘤题目 线段树+矩乘的更多相关文章
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】
题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过 1018,即使它在 ProblemSet 的第一页 ...
- [BZOJ 3888] [Usaco2015 Jan] Stampede 【线段树】
题目链接:BZOJ - 3888 题目分析 首先,计算出每个线段在 x 坐标 0 处出现的时间开始点和结束点,就转成了时间轴上的线段. 然后就是看每条线段是否被 y 比它小的线段完全覆盖了.注意求出的 ...
- bzoj 3489 A simple rmq problem - 线段树
Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...
- bzoj 3237 连通图 - 并查集 - 线段树
Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconne ...
- BZOJ.4695.最假女选手(线段树 Segment tree Beats!)
题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...
- bzoj 4311 向量 时间线建线段树+凸包+三分
题目大意 你要维护一个向量集合,支持以下操作: 1.插入一个向量(x,y) 2.删除插入的第i个向量 3.查询当前集合与(x,y)点积的最大值是多少.如果当前是空集输出0 分析 按时间线建线段树 大致 ...
- BZOJ 4942 NOI2017 整数 (压位+线段树)
题目大意:让你维护一个数x(x位数<=3*1e7),要支持加/减a*2^b,以及查询x的第i位在二进制下是0还是1 作为一道noi的题,非常考验写代码综合能力,敲+调+借鉴神犇的代码 3个多小时 ...
- BZOJ 2584: [Wc2012]memory(扫描线+线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...
随机推荐
- 52.基于doc value正排索引的聚合内部原理
主要知识点: 本节没有太懂,以后复习时补上 聚合分析的内部原理是什么????aggs,term,metric avg max,执行一个聚合操作的时候,内部原理是怎样的呢?用了什么样的数据结 ...
- (二)Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用
#!usr/bin/env python # -*- coding: utf-8 -*- def test(): print('hello, world') if __name__ == " ...
- 洛谷 1472 奶牛家谱 Cow Pedigrees
[题解] DP题,我们用f[i][j]表示有n个节点.高度小于等于j的二叉树的个数.f[i][j]=sigma(f[t][j-1]*f[i-t-1][j-1]) t是1~i-1范围内的奇数. #inc ...
- 使用JdbcTemplate和JdbcDaoSupport
[Spring对JDBC的支持] [JDBCTemplate简介] 1.为了是JDBC更加易于使用,Spring在JDBC API上定义了一个抽象层,以此建立一个JDBC存取框架. 2.作为Sprin ...
- 【Codeforces 369C】 Valera and Elections
[链接] 我是链接,点我呀:) [题意] 给你一棵树 让你选择若干个修理点. 这些修理点被选中之后,节点i到1号节点之间的所有"坏路"都会被修好 问最少需要选择多少个点才能将所有的 ...
- 解决Windows Server 2012 R2 Datacenter云服务器无法运行opencv python程序的问题
写了个基于opencv的python程序,pyinstaller 32位机打包后在win7/win10 32/64正常运行,在Windows Server 2012 R2 Datacenter云服务器 ...
- 一位ACMer过来人的心得
http://blog.csdn.net/acm_cxlove/article/details/8079348
- JQuery中如何重置(reset)表单(且清空隐藏域)
由于JQuery中,提交表单是像下面这样的: 所以,想当然的认为,重置表单,当然就是像下面这样子喽: 但是,不幸的是,这样写的话,会有一个让你很郁闷的结果,那就是,表单无法重置! 后来,上网查了一下, ...
- Cisco IOU Web Interface : Web IOU
https://github.com/dainok http://sns.clnchina.com.cn/space.php?uid=404779&do=blog&id=4298 ht ...
- HTML5:表格
表格的作用是显示二维数据.在HTML5中不再同意用表格控制页面内容的布局.而是採用新增的CSS表格特性(这里不涉及CSS,将在后面介绍). 以下主要介绍用于制作表格的HTML元素. 构建表格 表格的基 ...