E - Calc

E - Calc
题意:
举个栗子吧
abcde
要求的值就为
a ab abc abcd abcde b bc…之和

我们每修改一次某个值就要求一次和

我看到题就想到了线段树(我也不知道为什么)QWQ!!!

首先我打了一个线段树板子,只有一个t 数组 如果直接放进去
t 储存的值只是abced 中的一个段了,根本就不能求和。

要求和,先开个和的数组吧!反正也没什么用 ans数组(求和用的)

我们现在只有t 只能知道每个节点是abcde中的哪个段:

such as:abcde 是父亲 abc是儿子 de也是儿子,以此下分…

在这里插入图片描述

先画图一个图,如果想求ab这个节点的值怎么办呢,ANSab=a+b+ab,
那么ANSabc=a+b+c+ab+bc+abc,光是这两个值,是不可能单单用一个
t数组能解决的。

那怎么办?

如果能把儿子的节点的那些字母缀存起来就好了,对啊,就把它存起来!

比如:我们找ab节点以下的,1.a ab 2. b ba 我们得到了左右两个儿子节点的字母缀 推广一下 你就发现什么节点的和也能求出来了
用t1代表左边 ,t2代表右边 ,最底下的儿子 ANSa=a ANSb=b
ANSab = ANSa + ANSb + T1a T2b (ab)
那么t1为 T1=左边的儿子t *右边的儿子t1+左边的儿子t1
…t2类似…( 好像说的有点错误,但大概就是这个意思)

怎么说呢应该类似于多项式乘法吧,两边各记录 因子 相乘 即为这个节点的所有可能…

代码如下:

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define fo1(a,b) for(int a=0;a<b;++a)
#define fo2(a,b) for(int a=1;a<=b;++a)
#define inf 0x3f3f3f3f
#define S std::
using namespace std;
const int maxn=1e5+5;
const int mod=1e4+7;
int t[maxn<<2],t1[maxn<<2],t2[maxn<<2],ans[maxn<<2];
int n,m,a,b;
void pushup(int k){
    t[k]=t[k<<1]*t[k<<1|1];
    t1[k]=t1[k<<1|1]+t[k<<1|1]*t1[k<<1]%mod;
    t2[k]=t2[k<<1]+t2[k<<1|1]*t[k<<1]%mod;
    ans[k]=(ans[k<<1]+ans[k<<1|1])%mod+t1[k<<1]*t2[k<<1|1]%mod;
    t[k]%=mod;
    t1[k]%=mod;
    t2[k]%=mod;
    ans[k]%=mod;
}
void build(int k,int l,int r){
    t[k]=0;
    t1[k]=0;
    t2[k]=0;
    ans[k]=0;
    if(l==r)
        return ;
    else{
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        pushup(k);
    }
}
void update(int k,int l,int r,int w,int v){
    if(l==r&&l==w){
        t[k]=v;
        t1[k]=v;
        t2[k]=v;
        ans[k]=v;
    }
    else{
        int mid=l+r>>1;
        if(w<=mid)
            update(k<<1,l,mid,w,v);
        if(w>mid)
            update(k<<1|1,mid+1,r,w,v);
        pushup(k);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    fo2(i,m){
        scanf("%d%d",&a,&b);
        update(1,1,n,a,b);
        printf("%d\n",ans[1]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帮忙优化以下代码:public void runTask(ReportResultTask data, RunListener runListener) { UseMasterDataTypeEnum dataTypeEnum = ReportCommonLogicHelper.judgeTaskParam(data); // params.put(ReportCommonMasterDataRelationHelper.ParamTypeEnum.USE_MASTER_ENUM, dataTypeEnum.getValue()); params.put(ReportCommonMasterDataRelationHelper.ParamTypeEnum.YEAR_MONTH, data.getYearAndMonth()); try { List<ReportResultInventoryConsumablesNonFirst> saveList = Collections.synchronizedList(new ArrayList<>()); ReportNonFirstInvBO bo = new ReportNonFirstInvBO(); bo.setParams(params); bo.setYearMonth(Func.toLong(data.getYearAndMonth())); LiteflowResponse response = flowExecutor.execute2Resp("flow-calc-non-first-data", bo, ReportNonFirstInvBO.class); if (response.isSuccess()) { saveList = bo.getResults(); } if (saveList != null & saveList.size() > 0) { saveList.stream().forEachOrdered(fun -> { bo.setDistributorCode(fun.getNonFirstDistributorCode()); bo.setYearMonth(fun.getYearMonth()); bo.setIdo(BigDecimal.ZERO); fun.getNonFirstData().stream().forEach(fun1 -> { bo.setProductLine(fun1.getProductLine()); LiteflowResponse idoResponse = flowExecutor.execute2Resp("flow-calc-non-first-calcIdo", bo, ReportNonFirstInvBO.class); if (idoResponse.isSuccess()) { if (fun1.getProductLine().equals(IDO_TOTAL_PL)) { fun1.getItemData().stream().filter(fun2 -> ResultConstance.IDO_TOTAL.equals(fun2.getItemName())).forEach(x -> x.setItemValue(bo.getIdo())); } else { fun1.getItemData().stream().filter(fun2 -> ResultConstance.IDO.equals(fun2.getItemName())).forEach(x -> x.setItemValue(bo.getIdo())); } } }); }); this.updateSystemFieldInfo(saveList, data); inventoryConsumablesNonFirstService.insertBatch(saveList); runListener.complete(); } else { runListener.error(String.format("所选【%s-%s】产品/经销商主数据为空", data.getYearAndMonth(), "")); } } catch (Exception e) { log.error(StringUtil.format("非一级试剂耗材库存报表处理出错【{}】", e.getMessage()), e); runListener.error(StringUtil.format("非一级试剂耗材库存报表处理出错【{}】", e.getMessage())); } }
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值