题目链接:https://ac.nowcoder.com/acm/contest/892/D
题目大意:
思路:线段树维护区间的a1和an, 公差为1。
/****** POJ3468*******/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define MAX_NODE 400005
#define MAX_ 100005
struct NODE
{
ll l, r;
}node[MAX_NODE];
ll f[MAX_]; //记录节点i的node结构体数组下标f[i]
ll a1[MAX_NODE];
ll an[MAX_NODE];
void BT(ll i, ll l ,ll r) //建树
{
node[i].l=l;
node[i].r=r;
a1[i]=0;
an[i]=0;
if(l==r) //根节点
{
f[l]=i;
return;
}
BT((i<<1), l, (l+r)/2); //建左子树
BT((i<<1)+1, (l+r)/2+1, r);//建右子树
}
void upadd(ll i)
{
if(an[i])
{
a1[i<<1]=a1[i];
an[i<<1]=(a1[i]+an[i])/2;
a1[(i<<1)+1]=(a1[i]+an[i])/2+1;
an[(i<<1)+1]=an[i];
a1[i]=0;
an[i]=0;
}
}
void UP(ll i, ll l, ll r, ll L, ll R)//更新
{
if(node[i].l==l&&node[i].r==r)//找到更新区间
{
a1[i]=L;
an[i]=R;
return;
}
upadd(i); //把此本节点的add往下移动
ll mid=(node[i].l+node[i].r)/2;//继续寻找区间
if(r<=mid) //全在左区间
{
UP(i<<1, l, r, L, R);
}
else if(l>mid) //全在右区间
{
UP((i<<1)+1, l, r, L, R);
}
else
{
UP(i<<1, l, mid, L, L+(mid-l));
UP((i<<1)+1, mid+1, r, L+(mid-l)+1, R);
}
}
/*************/
ll ans=0; //记录每次的查询结果
/*************/
void FD(ll i, ll l, ll r) //查找
{
if(an[i]&&l==node[i].l&&r==node[i].r)
{
ans+=(a1[i]+an[i])*(an[i]-a1[i]+1)/2;
return;
}
upadd(i); //把此本节点的add往下移动
ll mid=(node[i].l+node[i].r)/2;//继续查询区间
if(r<=mid) //全在左区间
{
FD(i<<1, l, r);
}
else if(l>mid) //全在右区间
{
FD((i<<1)+1, l, r);
}
else //左右区间都有
{
FD(i<<1, l, mid);
FD((i<<1)+1, mid+1, r);
}
}
/*********************/
//建树 BT(1, 1 ,n);节点1-n
//查询 FD(1, a, b);[a, b]的信息
//更新 UP(1, a, b, c);//把区间的add+=a
int main()
{
ll n, m;
scanf("%lld%lld",&n,&m);
BT(1, 1, n);
UP(1, 1, n, 1, n);
while(m--)
{
ll a, b, c;
scanf("%lld%lld%lld",&a,&b,&c);
if(a==2)
{
ans=0;
FD(1, b, c);
printf("%lld\n",ans);
}
else
{
UP(1, b, c, 1, c-b+1);
}
}
return 0;
}