hdu6155

news/2024/11/25 17:33:31/

Subsequence Count

题目链接
ccpc网络赛1006
题意是给一个01字符串,然后有2种操作,
1、把l到r这个区间的字符翻转,
2、查询l到r这个区间有多少个不同的子序列,(注意是子序列,可不连续),对1e9+7取模
这个题目在比赛的时候过的人很少
其实对于第二种操作,我们容易得到一个dp[i][0/1]代表前i个字符以0/1结尾的不同子序列有多少个,容易得到方程

if(s[i] == 0)dp[i][0] =dp[i-1][0] + dp[i-1][1] + 1 

S[i] == 1同理,然后就是转化区间上的问题,容易想到用一些数据结构来维护,比如线段树,但是用线段树的话必须把这个递推的方程转化为一个可以区间合并的问题。我们知道dp转移有时候可以变为乘上一个矩阵,而且矩阵是满足结合律的,也就是说可以用来区间合并。
当S[i] 为1时,我们可以构造出一个矩阵A,S[i]为0时同理,可以构造出矩阵B
然后我们就可以用线段树来维护一个区间的矩阵的积,
在修改的时候,我们要把某个区间的A矩阵变为B,B矩阵变为A。我们可以对于一个节点可以记录一段区间翻转和未翻转的矩阵积,当某一个区间需要被翻转的时候,把未翻转矩阵和翻转矩阵交换一下即可。因为有Push_up的存在,保证了节点里矩阵是正确的。

#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define  LONG long long
const LONG  INF=0x3f3f3f3f;
const LONG  MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
#define lson  l , mid , rt<< 1
#define rson  mid + 1 ,r , (rt<<1)|1
#define root 1, n , 1
const int MAXN  = 1e5 +100 ;
struct Matr
{LONG  matr[3][3] ;void Init(){clr0(matr) ;}
};
Matr x ,y ;
struct Tree
{Matr Real ;Matr Temp ;
} tree[MAXN<<2] ;
int lazy [MAXN<<2] ;
char S[100100] ;
Matr Multi(Matr a , Matr b)
{Matr ret ;ret.Init() ;for(int i = 0;i < 3 ; ++i)for(int j = 0 ;j<  2 ;  ++ j)for(int k=0;k< 3; ++k)ret.matr[i][j] = ( ret.matr[i][j] + a.matr[i][k] * b.matr[k][j] ) %MOD ;ret.matr[2][2]= 1;return ret;
}
void Push_up(int rt )
{tree[rt].Real = Multi(tree[rt<<1].Real , tree[rt<<1|1].Real) ;tree[rt].Temp = Multi(tree[rt<<1].Temp , tree[rt<<1|1].Temp ) ;
}
void Build(int l , int r , int rt)
{lazy[rt] = 0;if(l == r ){if(S[l] == '0'){tree[rt].Real = y ;tree[rt].Temp = x ;}else{tree[rt].Real = x ;tree[rt].Temp = y ;}return ;}int mid = (l + r ) /2 ;Build(lson ) ;Build (rson ) ;Push_up(rt) ;
}
void Push_down(int rt )
{if(lazy[rt]){Matr tmp = tree[rt<<1].Real ;tree[rt<<1].Real = tree[rt<<1].Temp ;tree[rt<<1].Temp = tmp ;tmp = tree[rt<<1|1 ].Real ;tree[rt<<1|1].Real = tree[rt<<1|1].Temp ;tree[rt<<1|1].Temp = tmp ;lazy[rt<<1] ^= 1 ;lazy[rt<<1|1] ^= 1;lazy[rt] = 0 ;}
}
void Update(int L ,int R , int l, int r ,int rt )
{if(L <= l &&r <= R){lazy[rt] ^= 1;Matr tmp = tree[rt].Real ;tree[rt].Real = tree[rt].Temp ;tree[rt].Temp = tmp ;return ;}Push_down(rt) ;int mid = (l + r) / 2;if(L <= mid)Update(L, R , l, mid , rt<<1 ) ;if(R > mid )Update(L,R , mid + 1 , r , rt<<1|1) ;Push_up(rt) ;}
Matr Que(int L ,int R ,int l , int r ,int rt )
{if(L <= l &&r <= R ){return tree[rt].Real ;}Push_down(rt) ;int mid = (l +r) / 2;Matr res ;res.Init() ;res.matr[0][0] =1 , res.matr[2][2] = 1 , res.matr[1][1] = 1;if(L <=mid )res = Multi( res ,Que(L , R , lson ) ) ;if(R > mid)res = Multi(res , Que(L ,R ,rson ) ) ;return res ;
}
int main()
{int T ;cin >>T ;x.Init() ;y.matr[0][0] = 1 ,y.matr[1][0] = 1,y.matr[2][0] = 1 ,y.matr[0][1] = 0,y.matr[1][1] = 1 ,y.matr[2][1] = 0,y.matr[0][2] = 0 ,y.matr[1][2] = 0, y.matr[2][2] = 1;x.matr[0][0] = 1 ,x.matr[1][0] = 0,x.matr[2][0] = 0 ,x.matr[0][1] = 1,x.matr[1][1] = 1 ,x.matr[2][1] = 1,x.matr[0][2] = 0 ,x.matr[1][2] = 0, x.matr[2][2] = 1;int n , Q ;while(T --){scanf("%d%d",&n,&Q) ;scanf("%s",S+1) ;Build( root )  ;while(Q -- ){int op ;scanf("%d",&op) ;int l, r ;if(op == 1){scanf("%d%d",&l,&r) ;Update(l ,r ,root ) ;}else{scanf("%d%d",&l , &r) ;Matr res ;res = Que(l , r ,root ) ;printf("%lld\n",(res.matr[2][0] + res.matr[2][1] ) % MOD ) ;}}}return 0 ;
}

http://www.ppmy.cn/news/507302.html

相关文章

IEC61850

IEC 61850是关于变电站自动化系统结构和数据通信的国际标准&#xff0c;目的是使变电站内不同厂家的智能电子设备(IED)之间通过一种标准实现互操作和信息共享&#xff0c;取消多种协议转换环节和转换设备&#xff0c;使系统调试更加便捷&#xff0c;实现“一个世界、一种技术、…

【面经】重庆农商行金融科技面经

【面经】重庆农商行金融科技面经 在脉脉上看重庆农商行貌似钱多事少&#xff0c;好评比较多。 公司介绍 重庆农村商业银行股份有限公司&#xff08;以下简称“重庆农商行”&#xff09;前身为重庆市农村信用社&#xff0c;成立于1951年&#xff0c;至今已有70余年历史。2003年…

联发科mt6165芯片原理图mt6165芯片资料

mt6165是在40nm cmos中实现的td-scdma和2g双模rf收发器。闯客网rf收发器函数是完全集成的。这份文件描述了rf的性能目标。在整个产品中嵌入宏 关键特征 -成本低的双模射频解决方案&#xff08;gge和td-scdma&#xff09;。8(hspa))四频gge(gsm850/900/dcs/pcs)/三频tdd(b34/b39…

Pyqt5的QThead线程对象实现线程开始、暂停、恢复、结束

前言 最近学习Pyqt5&#xff0c;研究QThead线程对象&#xff0c;因网上这方面资料较少&#xff0c;钻研过后&#xff0c;将感悟理解记录如下。 声明&#xff1a;感悟理解建立在分析其他大佬的博客的基础上&#xff0c;喝水不忘挖井人&#xff0c;大佬们的博客如下&#xff1a…

联想e480一键恢复小孔_thinkpade480win10如何一键还原

thinkpade480win10如何一键还原 卡饭网 本站整理 2019-08-14 方法一&#xff1a; 在控制面板中打开“恢复”(大图标查看方式下)。 点击【开始系统还原】 选择还原点 (1)系统还原会推荐一个最近的没有故障的还原点&#xff0c;建议选择。点击【下一步】&#xff0c;再点击【完成…

E480安装ubuntu18.04出现进入wifi没有无线适配器的处理方案

今天突发奇想&#xff0c;想在自己的电脑上装上ubuntu&#xff0c;实现win10ubuntu双系统 在顺利的装好系统之后&#xff0c;发现wifi界面找不到适配器&#xff0c;也即是无线网卡没有装好 E480是rtl8821ce无线网卡&#xff0c;官方不提供linux驱动&#xff0c;github上大佬写…

Java 基础进阶篇(十八):正则表达式匹配规则和应用

文章目录 一、正则表达式概述二、正则表达式的匹配规则三、正则表达式在方法中的应用3.1 校验手机号、邮箱和座机电话号码3.2 字符串的内容替换和分割 四、编程题目4.1 表示数值的字符串4.2 非严格递增连续数字序列 一、正则表达式概述 正则表达式是对字符串&#xff08;包括普…

ubuntu16.04误删高于当前版本内核,开机黑屏,只显示/dev/sda9:clean...files,...blocks,更换内核后卡在开机界面,解决安装包依赖,重新安装ubuntu桌面解决问题

1 背景介绍 1 起因 我使用的Ubuntu16.04在安装的过程中/boot只分了200M空间&#xff0c;导致后续更新的过程中被新内核占满了空间&#xff0c;当时boot中所包含的内核有*linux-image-4.15.0-28-generic&#xff0c;linux-image-4.15.0-43-generic&#xff0c;linux-image-4.1…