hihoCoder - 1116 - 计算 (线段树区间合并)

本文介绍了一种线段树区间合并的实现方法,通过维护每个区间的答案、前缀和后缀信息来高效地处理区间更新问题。文章提供了两种实现方式:一种使用组合数学优化并借助二进制特性;另一种采用map维护前后缀,尽管运行速度较慢但易于理解。
线段树区间合并的题目套路就是每一段维护
1.当前段的答案data[k],
2.当前段所有前缀Left[k]
3.当前段所有后缀Right[k]
合并时由当前段的左右子节点的data转移当前段,
还有左子节点的后缀与右子节点的前缀合并形成的区间对当前段的贡献。
然后维护当前段Left,Right就ok了。

现在很少看见用vect或者map维护每一段前后缀的了(我会说是跑的太慢了吗)。
一般都会用组合数学优化一下或者二进制优化。
这里也不例外,当前段的每一个前后缀都是乘积Left,Right只是这些前后缀的和,

合并原理类似多项式乘法,(和的乘积等于两个多项式的乘积)


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#define mid (l+r>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
const int mod=10007;
const int maxn=1e5+7;
int data[maxn*4];
int Len[maxn*4];
int Left[maxn*4],Right[maxn*4];

void update(int k,int l,int r,int p,int v){
    if(p<l||r<p)return ;
    if(l==r){
        Len[k]=Left[k]=Right[k]=data[k]=v%mod;
        return ;
    }
    if(p<=mid) update(lson,p,v);
    else update(rson,p,v);
    data[k]=(data[k<<1]+data[k<<1|1])%mod;
    data[k]=(data[k]+(Right[k<<1]*Left[k<<1|1])%mod)%mod;
    Left[k]=((Len[k<<1]*Left[k<<1|1])%mod+Left[k<<1])%mod;
    Right[k]=((Len[k<<1|1]*Right[k<<1])%mod+Right[k<<1|1])%mod;
    Len[k]=(Len[k<<1]*Len[k<<1|1])%mod;
}

int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q)){
        int siz=min(n*8,maxn*4);
        fill(data,data+siz,0);
        fill(Left,Left+siz,0);
        fill(Right,Right+siz,0);
        for(int i=0;i<q;i++){
            int p,v;
            scanf("%d%d",&p,&v);
            update(1,1,n,p,v);
            printf("%d\n",data[1]%mod);
        }
    }
    return 0;
}














放上我SB的map。



#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#define mid (l+r>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
const int mod=10007;
const int maxn=1e5+7;
int data[maxn*4];
int Len[maxn*4];
map<int,int > Left[maxn*4],Right[maxn*4];
map<int,int>::iterator it,ip;


void update(int k,int l,int r,int p,int v){//printf("k==%d l==%d r==%d\n",k,l,r);
    if(p<l||r<p)return ;
    if(l==r){
        data[k]=v%mod;
        Left[k].clear();
        Right[k].clear();
        Left[k][(v%mod)]=1;
        Right[k][(v%mod)]=1;
        Len[k]=v%mod;//printf("data[%d]==%d \n",k,data[k]);
        return ;
    }
    if(p<=mid) update(lson,p,v);
    else update(rson,p,v);
    data[k]=(data[k<<1]+data[k<<1|1])%mod;
    for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){
        for(ip=Left[k<<1|1].begin();ip!=Left[k<<1|1].end();ip++){
            int t1=it->first%mod,t2=it->second%mod,t3=ip->first%mod,t4=ip->second%mod;
            //printf("k== %d t1=%d t2=%d t3=%d t4=%d\n",k,t1,t2,t3,t4);
            int t5=((((t1*t3)%mod)*t2)%mod)*t4%mod;
            data[k]=(data[k]+t5)%mod;
        }
    } //printf("haha\n");
    Left[k].clear();
    for(it=Left[k<<1|1].begin();it!=Left[k<<1|1].end();it++){
        int t1=it->first%mod,t2=it->second%mod;
        Left[k][(t1*Len[k<<1])%mod]=(Left[k][(t1*Len[k<<1])%mod]+t2)%mod;
    }
    for(it=Left[k<<1].begin();it!=Left[k<<1].end();it++)
    Left[k][(it->first)%mod]=(Left[k][(it->first)%mod]+it->second)%mod;//printf("haha2\n");
    ///////
    Right[k].clear();//printf("%d %d\n",Right[k<<1].size(),Right[k<<1|1].size());
    for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){
        int t1=it->first%mod,t2=it->second%mod;//printf("k<<1==%d %d %d \n",k<<1,t1,t2);
        Right[k][(t1*Len[k<<1|1])%mod]=(Right[k][(t1*Len[k<<1|1])%mod]+t2)%mod;
        //Right[k].push_back((Right[k<<1][i]*Right[k<<1|1][0])%mod);//printf("Right[k]==%d*%d \n",Right[k<<1][i],Right[k<<1|1][0]);
    }
    for(it=Right[k<<1|1].begin();it!=Right[k<<1|1].end();it++)
    Right[k][it->first%mod]=(Right[k][it->first%mod]+it->second%mod)%mod;//printf("haha3\n");
    Len[k]=(Len[k<<1]*Len[k<<1|1])%mod; //printf("data[%d]==%d Len %d %d %d\n",k,data[k],Len[k],Len[k<<1],Len[k<<1|1]);
}

void debug(int k,int l,int r){
    printf("debug k==%d data=%d Len=%d Left=%d Right=%d\n",k,data[k],Len[k],Left[k].size(),Right[k].size());
    for(it=Left[k].begin();it!=Left[k].end();it++)printf("Left  k==%d %d %d\n",k,it->first,it->second);
    for(it=Right[k].begin();it!=Right[k].end();it++)printf("Right  k==%d %d %d\n",k,it->first,it->second);
    if(l==r)return ;
    debug(lson);
    debug(rson);
}

int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q)){
        int siz=min(n*8,maxn*4);
        fill(data,data+siz,0);
        for(int i=0;i<siz;i++){
            Left[i].clear();//Left[i][0]=1;
            Right[i].clear();//Right[i][0]=1;
        }//debug(1,1,n);
        for(int i=0;i<q;i++){
            int p,v;
            scanf("%d%d",&p,&v);
            update(1,1,n,p,v);
            //printf("-----------\n");debug(1,1,n);printf("--------------\n");
            printf("%d\n",data[1]%mod);
        }
    }
    return 0;
}













先展示下效果 https://pan.quark.cn/s/5061241daffd 在使用Apache HttpClient库发起HTTP请求的过程中,有可能遇到`HttpClient`返回`response`为`null`的现象,这通常暗示着请求未能成功执行或部分资源未能得到妥善处理。 在本文中,我们将详细研究该问题的成因以及应对策略。 我们需要掌握`HttpClient`的运作机制。 `HttpClient`是一个功能强大的Java库,用于发送HTTP请求并接收响应。 它提供了丰富的API,能够处理多种HTTP方法(例如GET、POST等),支持重试机制、连接池管理以及自定义请求头等特性。 然而,一旦`response`对象为`null`,可能涉及以下几种情形:1. **连接故障**:网络连接未成功建立或在请求期间中断。 需要检查网络配置,确保服务器地址准确且可访问。 2. **超时配置**:若请求超时,`HttpClient`可能不会返回`response`。 应检查连接和读取超时设置,并根据实际需求进行适当调整。 3. **服务器故障**:服务器可能返回了错误状态码(如500内部服务器错误),`HttpClient`无法解析该响应。 建议查看服务器日志以获取更多详细信息。 4. **资源管理**:在某些情况下,如果请求的响应实体未被正确关闭,可能导致连接被提前释放,进而使后续的`response`对象为`null`。 在使用`HttpClient 3.x`版本时,必须手动调用`HttpMethod.releaseConnection()`来释放连接。 而在`HttpClient 4.x`及以上版本中,推荐采用`EntityUtils.consumeQuietly(respons...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值