这种题目一般是一个权值线段树套一个区间线段树可以改成树状数组套线段树。。。不解释了很常规......树套树恶心
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
unsigned int sum[15000010], tree[300000], lson[15000010], rson[15000010],t[15000010];
unsigned int n, m;
unsigned int cnt = 1;
void intervaladd(unsigned int &num, int l, int r,int nowl,int nowr)
{
if (nowl > r || nowr < l)return;
if (num == 0)
num = cnt++;
int mid = (nowl + nowr) >> 1;
if (nowl >= l&&nowr <= r)
{
sum[num] += (nowr - nowl + 1);
t[num]++;
//cout << "num:"<<num<<" "<<"posl:" << l << "posr:" << r << " " << "nowposl:" << nowl << " " << "nowposr:" << nowr << "sum:"<<sum[num]<<endl;
return;
}
if (mid >= l&&nowl <= r)intervaladd(lson[num], l, r, nowl, mid);
if (mid < r&&nowr>=l)intervaladd(rson[num], l, r, mid + 1, nowr);
sum[num] = sum[lson[num]] + sum[rson[num]] + t[num] * (nowr - nowl + 1);
//cout <<"num:"<<num<<" "<<"l:" << l << "r:" << r << " " << "nowl:" << nowl << " " << "nowr:" << nowr << "sum:" << sum[num] << endl;
}
unsigned int intervalquery( int num, int l, int r, int nowl,int nowr)
{
if (nowl > r || nowr < l)
return 0;
int mid = (nowl + nowr) >> 1;//这个又写错了 论写代码专注思路清晰的重要性......
if (num == 0)
return 0;
if (nowl >= l&&nowr <= r)
{
//cout <<"num:"<<num<<" "<< "posl:" << " " <<nowl << " " << "posr:" << nowr<< " " << "sum:"<<sum[num] << endl;
return sum[num];
}
unsigned int kl = 0; unsigned int kr = 0;
if (mid>=l)
kl = intervalquery(lson[num], l, r, nowl, mid);
if (mid<r)
kr = intervalquery(rson[num], l, r, mid + 1, nowr);
//cout << "posl:" << " " << nowl << " " << "posr:" << nowr << " " << "sum:"<<(min(nowr, r) - max(l, nowl) + 1)*t[num] + kl + kr << endl;
return (min(nowr, r) - max(l, nowl) + 1)*t[num] + kl + kr;
}
void addvalue( int a, int b, int c)
{
int l = 0; int r = 2*n;
c += n;
int id = 1;
while (l <=r)
{
//cout << endl;
//cout << "begin:" << "l:"<<l<<" "<<"r:"<<r<<endl;
intervaladd(tree[id], a, b, 1, n);
//cout << "end:" << endl;
//cout << endl;
unsigned int mid = (l + r) >> 1;
if (l == r)break;
c<=mid ? (id = 2 * id, r = mid ): (id = 2 * id + 1, l = mid + 1);//这一定要加括号
}
}
int queryvalue(int a, int b, unsigned int c)
{
int l = 0; int r = n * 2;
int id = 1;
while (l < r)
{
int mid = (l + r) >> 1;
//cout << endl;
//cout << "begin:" << "numl:" << mid + 1 << " " << "numr:" << r << " " << "posl:" << a << " " << "posr:" << b << " " << endl;
unsigned int k = intervalquery(tree[id * 2 + 1], a, b, 1, n);
//cout << "result:" << k << endl;
// cout << "end:" << endl;
// cout << endl;
if (c > k)
{
c -= k;
r = mid;
id = id * 2;
}
else
{
l = mid+1;
id = 2 * id+1;
}
}
return l-n;
}
int main()
{
scanf("%d%d", &n, &m);
int op;
for (int i = 0; i < m; i++)
{
scanf("%d", &op);
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (op == 1)
{
addvalue(a, b, c);
}
else
printf("%u\n", queryvalue(a, b, c));
}
}