做题心得

1.矩阵加速的通法
形式1:dp[i]=a1*dp[i-1]+a2*dp[i-2]+…+a[k]*dp[i-k]

for(int i=0;i<k;i++) A.ma[i][0]=chu[i]
for(int i=0;i<k;i++)
    for(int j=0;j<k;j++){
        if(i==0) B.ma[i][j]=a[j+1];
        else B.ma[i][j]=(j==(i-1))?1:0;
    }

形式2:dp[i][j]=a[j][0]*dp[i-1][0]+a[j][1]*dp[i-1][1]+…+a[j][k-1]*dp[i-1][k-1],0<=j< k
求dp[n][0],dp[n][1]…dp[n][k-1],n<=1e9,k<=50

for(int i=0;i<k;i++) A.ma[i][0]=chu[i];
for(int i=0;i<k;i++)
    for(int j=0;j<k;j++){
        B.ma[i][j]=a[i][j]
    }

2.常见dp优化方法
dp[i]=f(dp[j]),1<=j<=i1
1)尺取法优化
适用于dp的最优解转移沿着特定方向
2)辅助数组法
适用于可以通过适当变换将i和j分离开,数组记录g[j]用于更新dp[i]
3)辅助数据结构优化
dp[i]=min/maxf(dp[j])h1[i]<h2[j]
解法:将元素按照h1的值从小到大重新排序,由于h1[i]递增,所以不满足 h1[i]<h2[j] 的一定不满足 h1[i+1]<h2[j] ,所以可以使用优先队列维护排好序的前面所有项的最小/最大f(dp)值,并记录相应的h2值,如果队头元素对当前i不满足 h1[i]<h2[queue[top]] ,队头元素出列。进出列各一次,复杂度O(n)
dp[i]=min/maxf(dp[j])h1[i]>h2[j]
解法:将元素按照h2的值从小到大排序,维护f(dp)值递减/增的序列,对于不满足递减/增性质的f(dp)值舍去即可。原因是h2递增,对于满足 h2[j]<h1[i ]的值一定对于所有的 k<j 都满足 h2[k]<h1[i] ,所以如果当前 f(dp[j])<f(dp[j1]) ,则下标大于j的dp值一定不会通过第j项转移,否则也可以通过第j-1项转移,第j项删除不影响结果,因此最终只要二分查找满足 h2[j]<h1[i] 的最大下标项即可。 dp[i]=f(dp[bisearch(s+1,s+top+1,h1[i])]) ,s中存储h2和排好序的数组下标值,对h2进行二分,输出相应下标值。
两者比较可知,如果dp[i]仅与某一项有关,限制条件i和j完全独立,每次都将元素按照限制条件较小的一边重新进行排序即可进行“维护队列”优化

然而上述两中dp形式都可以很容易地通过线段树进行优化,两种方法各有优劣。
如第二种形式,先将所有f(dp)值按h2的值为下标插入线段树中,然后每次询问小于h1[i]的f(dp)最小值,从复杂度O(n*logn)

从而我们联想到此种dp的通法:
**形如 dp[i]=min/max/sumf(dp[j])h2[i]<=h1[j]<=h3[i] ,我们可以通过线段树/树状数组进行优化求解。
min/max:线段树求解。在h1值上建立以f(dp)为值的线段树,将所有值插入后,每次更新dp值时询问h2[i]-h3[i]区间内的min/max值即可
sum:同理建立树状数组,每次询问区间和即可

栈或队列优化题目汇总
1)求l[i]:第i个数左侧个小于i位置元素的最大位置
维护单调栈即可

3.实际简化模型
1)三角简化
元素中两两之间只有两种互斥关系A和!A,求三个数之间两两为A或两两!A的三元组数目
C(n,3)- ni=1a[i](n1a[i]) ,a[i]是与第i个元素关系为A的数目

常见问题求解方法
1)连续区间的求和统计问题:以区间和为主元,统计以“某点开始”、“相等区间和”对应的权值和。因为连续区间满足连续变化的性质,所以可以采取尺取法统计。
2)字符串问题
预处理Hash(i):前i个字符的哈希值,可以在O(1)得到字串hash值
3)二分答案
1.求 min(max(f(xi),1<=i<=n)),g(x1,x2...xn)=0
二分答案。令min值为L,判断是否存在 max(f(xi),1<=i<=n)<L 。判断方法如下:将n个不等式处理后相加凑成 g(x1,x2...xn) ,将g函数放宽为 >=0 ,可以得到L和参数之间的关系,二分答案L即可得到恰好满足不等关系的最小L,如果不一定恰好取等,先令每个f(x_i)=L,然后再对每个 xi 进行缩小使得满足g函数等式关系。

2.求 max(f(xi1,xi2...xik)/g(xi1,xi2...xik)),1<=i1<i2<...<ik<=n
令max值为L,判断是否存在序列满足 max(f(xi1,xi2...xik)/g(xi1,xi2...xik) 大于等于L.可以通过建图,网络流求解方法

4)计数问题
概率法解决计数问题:设总的方案数为sum,满足条件的概率为p,那么满足条件的计数为ans=p*sum。如此一来就把计数问题转化为概率问题!

3.dfs的应用
1)动态记录访问到当前节点时的所需信息(仅在进入该节点时定义为访问),然后在入戳和出戳时分别记录当前节点的信息,比较差距即可得到以该点为根的子树的所需信息总和

4.生成树问题
1)无向图多组询问,从u出发仅经过长度不大于x的边可到达的点的个数
解法:利用kruskal算法建立最小生成树,在合并两点x和y所在子树时,着大x和y所在子树的跟fx和fy,然后让它们同时指向新节点f,f赋值为该边权值,最终得到2*n-1个节点。这个生成树的性质为:从深到浅,权值不断增大。可以查找从u到根节点权值小于x的最大节点f,f子树节点即为u所能到达的节点集合。求节点数量的话,先预处理子树大小或者记录dfs序都可以

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值