洛谷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 ;
}

完结撒花ヽ(゚∀゚)メ(゚∀゚)ノ

posted @ 2021-10-29 16:10  theStarMaster  阅读(52)  评论(0编辑  收藏  举报