CSP 202312-4 宝藏 100分题解

本文讲述了作者在解决CCF-CSP认证考试中一道关于矩阵运算的问题时的经历,重点介绍了如何使用Matx结构和优化代码(如cin.tie(0)和cout.tie(0))以减少内存使用和提高运行效率,最终达到800ms的执行时间。
摘要由CSDN通过智能技术生成

csp该题链接

202312-4 宝藏

debug了两天,最后参考了@Pujx的CCF-CSP认证考试 202312-4 宝藏 100分题解​​​​​​才勉强过的,讲解也看大佬的吧。附上个人基本照抄的代码。(不加优化指令和输入输出加速时间刚好1.5s,加上后优化到800ms+,主要是cin.tie(0)和cout.tie(0)的作用,内存在9MB左右)

#pragma GCC optimize(2,3,"Ofast","inline")
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
using namespace std;
const int M=998244353;
int n,m,len;
struct Matx
{
    int m[2][2]={{1,0},{0,1}};
    friend Matx operator*(const Matx &a,const Matx &b)
    {
        Matx temp;
        temp.m[0][0]=(1LL*a.m[0][0]*b.m[0][0]+1LL*a.m[0][1]*b.m[1][0])%M;
        temp.m[0][1]=(1LL*a.m[0][0]*b.m[0][1]+1LL*a.m[0][1]*b.m[1][1])%M;
        temp.m[1][0]=(1LL*a.m[1][0]*b.m[0][0]+1LL*a.m[1][1]*b.m[1][0])%M;
        temp.m[1][1]=(1LL*a.m[1][0]*b.m[0][1]+1LL*a.m[1][1]*b.m[1][1])%M;
        return temp;
    }
    friend istream& operator>>(istream &in,Matx &mx)
    {
        return in>>mx.m[0][0]>>mx.m[0][1]>>mx.m[1][0]>>mx.m[1][1];
    }
    friend ostream& operator<<(ostream &out,const Matx &mx)
    {
        return out<<mx.m[0][0]<<' '<<mx.m[0][1]<<' '<<mx.m[1][0]<<' '<<mx.m[1][1];
    }
};
struct Order
{
    int v;
    Matx matl,matr;
    friend istream& operator>>(istream &in,Order &od)
    {
        od.matl=od.matr=Matx(); 
        in>>od.v;
        if(od.v==1)
            in>>od.matl;
        else if(od.v==2)
            in>>od.matr;
        return in;
    }
};
vector<Order> order;
struct Block
{
    int l,r,neg,sz,id;
    vector<Matx> suml,sumr;
    static int idx;
    Block()
    {
        id=idx++;
        l=id*len; r=min(l+len,n);
        build();
    }
    void build()
    {
        neg=0;
        suml.clear();   sumr.clear();
        vector<int> matx;
        for(int i=l;i<r;i++)
        {
            if(order[i].v!=3)       matx.push_back(i);
            else if(matx.size())    matx.pop_back();
            else    neg++;
        }
        sz=matx.size();
        suml.push_back(Matx()); sumr.push_back(Matx());
        for(auto i:matx)
        {
            suml.push_back(order[i].matl*suml.back());
            sumr.push_back(sumr.back()*order[i].matr);
        }
    }
};
int Block::idx=0;
vector<Block> block;
Matx query(int l,int r)
{
    int bl=l/len,br=r/len;
    if(bl==br)
    {
        vector<int> matx;
        for(int i=l;i<=r;i++)
        {
            if(order[i].v!=3)       matx.push_back(i);
            else if(matx.size())    matx.pop_back();
        }
        Matx L,R;
        for(auto i:matx)
        {
            L=order[i].matl*L;
            R=R*order[i].matr;
        }
        return L*R;
    }
    else
    {
        int neg=0;
        Matx L,R;
        vector<int> matx;
        for (int i=block[br].l;i<=r;i++)
        {
            if(order[i].v!=3)       matx.push_back(i);
            else if(matx.empty())   neg++;
            else matx.pop_back();
        }
        for(auto i:matx)
        {
            L=order[i].matl*L;
            R=R*order[i].matr;
        }
        for(int i=br-1;i>bl;i--)
        {
            if(neg>=block[i].sz)
                neg=neg-block[i].sz+block[i].neg;
            else
            {
                L=L*block[i].suml[block[i].sz-neg];
                R=block[i].sumr[block[i].sz-neg]*R;
                neg=block[i].neg;
            }
        }
        matx.clear();
        for(int i=l;i<block[bl].r;i++)
        {
            if(order[i].v!=3)       matx.push_back(i);
            else if(matx.size())    matx.pop_back();
        }
        while(neg&&!matx.empty())   neg--,matx.pop_back();
        for(int i=matx.size()-1;i>=0;i--)
        {
            L=L*order[matx[i]].matl;
            R=order[matx[i]].matr*R;
        }
        return L*R;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin>>n>>m;
    len=sqrt(n);
    for(int i=0;i<n;i++)
    {
        order.push_back(Order());
        cin>>order.back();
    }
    for(int i=0;i<n;i+=len)
        block.push_back(Block());
    while(m--)
    {
        int v;
        cin>>v;
        if(v==1)
        {
            int i;
            cin>>i;
            cin>>order[--i];
            block[i/len].build();
        }
        else
        {
            int l,r;
            cin>>l>>r;
            cout<<query(--l,--r)<<endl;
        }
    }
    return 0;
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对不起,由于我是一个文本交互的模型,我无法提供图像内容或直接链接到具体的题解或解决方案。但是,我可以帮你理解CSP-J2019公交换乘问题的基本概念和解决策略,这通常涉及到数据结构、图论以及算法设计。 CSP-J2019中的公交换乘问题可能是一个典型的旅行商问题(Traveling Salesman Problem, TSP)变种,或者是寻找最优路径的问题,其中涉及到公交网络中不同站点之间的最短路径或最少换乘次数。解决此类问题通常需要使用动态规划、贪心算法或者一些启发式搜索算法,比如A*搜索或Dijkstra算法。 如果你需要了解题目的基本思路,可能会这样操作: 1. 建立一个图,节点代表公交站点,边代表两个站点之间的路线及其长度或换乘次数。 2. 对于每个节点,计算从起点到所有其他节点的最短路径,形成一个邻接矩阵或邻接表。 3. 使用动态规划方法,例如记忆化搜索,尝试所有可能的路径,每次选择当前未访问节点中距离最近的一个,直到遍历完所有节点并回到起点,记录下总的距离或换乘次数。 4. 为了优化,可以考虑使用启发式搜索策略,如用估算的总距离作为启发信息,优先探索看起来更优的路径。 如果你对具体解法有疑问,或者想了解某个步骤的详细操作,请告诉我,我会尽力解释。至于详细的题解,建议你查阅相关的代码库、论坛帖子或在线教程,它们通常会有文字描述和步骤示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值