洛谷P7870兔已着陆
P7870 兔已着陆
1.解题过程 :
比赛时读完题后先想的是手写个栈暴力搞,后来看见 \(k \le 1e12\) 后就知道此题数组开不下,然后就想怎么开数组才能搞这道题一看操作数 \(n \le 5e5\),完全可以开数组,然后又看见了插入的数是 \(l \cdots r\) 的等差数列,所以利用等差数列求和公式就可以免去枚举了。
2.细节
(对于每个 \(1\) 操作记一下 \(l\) , \(r\) , 下文的块)
首先看到 \(l , r \le 1e6\) , \(k \le 1e12\) , 就知道这必然要开 \(long~long\) (要不是测了大样例我就折在这了)。
其次就是取数的过程,我们先 \(k\) 减大块,大块清零,\(ans\) 加上大块的 \(l \cdots r\) 序列和,减完后( \(k\) 小于下一个块的长度),下一个块的 \(r\) 减去剩下的 \(k\) , \(ans\) 加上所删的序列和。
3.代码
#include<bits/stdc++.h>
using namespace std ;
#define int long long
class StarMaster
{
public :
inline int read()
{
int x = 0 , f = 1 ;
char ch = getchar() ;
while(ch > '9' || ch < '0')
{
if(ch == '-') f = -1 ;
ch = getchar() ;
}
while(ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48) ;
ch = getchar() ;
}
return x * f ;
}
struct node
{
int l , r ;
}a[5000010] ;
int n , tot ;
inline void work()
{
n = read() ;
for(int i = 1 ; i <= n ; ++ i)
{
int opt = read() ;
if(opt == 1)
{
a[++ tot].l = read() , a[tot].r = read() ;
}
else
{
int k = read() ;
long long sum = 0 ;
while(k > a[tot].r - a[tot].l + 1)
{
k -= (a[tot].r - a[tot].l + 1) ;
sum += (a[tot].r + a[tot].l) * (a[tot].r - a[tot].l + 1) / 2 ;
tot -- ;
}
if(k == 0)
{
cout << sum << '\n' ;
continue ;
}
int l = a[tot].r - k + 1 ;
sum += (a[tot].r + l) * k / 2 ;
a[tot].r -= k ;
cout << sum << '\n' ;
}
}
}
} Star ;
signed main()
{
// freopen("stack.in" , "r" , stdin) ;
// freopen("stack.out" , "w" , stdout) ;
Star.work() ;
return 0 ;
}
完结撒花ヽ(゚∀゚)メ(゚∀゚)ノ