博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4293: [PA2015]Siano
阅读量:4517 次
发布时间:2019-06-08

本文共 4984 字,大约阅读时间需要 16 分钟。

4293: [PA2015]Siano

Time Limit: 30 Sec Memory Limit: 256 MB

Submit: 546 Solved: 188
[Submit][Status][Discuss]

Description

农夫Byteasar买了一片n亩的土地,他要在这上面种草。

他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘米。
Byteasar一共会进行m次收割,其中第i次收割在第d[i]天,并把所有高度大于等于b[i]的部分全部割去。Byteasar想知道,每次收割得到的草的高度总和是多少,你能帮帮他吗?

Input

第一行包含两个正整数n,m(1<=n,m<=500000),分别表示亩数和收割次数。

第二行包含n个正整数,其中第i个数为a,依次表示每亩种植的草的生长能力。
接下来m行,每行包含两个正整数d[i],b,依次描述每次收割。
数据保证d[1]<d[2]<...<d[m],并且任何时刻没有任何一亩草的高度超过10^12。

Output

输出m行,每行一个整数,依次回答每次收割能得到的草的高度总和。

Sample Input

4 4

1 2 4 3

1 1

2 2

3 0

4 4

Sample Output

6

6

18

0

HINT

第1天,草的高度分别为1,2,4,3,收割后变为1,1,1,1。

第2天,草的高度分别为2,3,5,4,收割后变为2,2,2,2。

第3天,草的高度分别为3,4,6,5,收割后变为0,0,0,0。

第4天,草的高度分别为1,2,4,3,收割后变为1,2,4,3。

Source

By Claris

题解

此题卡常,疯狂TLE,最终没过,但是在洛谷团队里过了,正确性有保证。

首先按照a排序,发现不管怎么割草的长度都是单调的。
这样我们就很容易二分的找到割的位置,查询长度和,并修改即可。
用线段树。
记录 区间内最晚的最近一次被割的草被割时间为last ,到last时间区间内草长度和sum ,区间是否被割标记,到last时间最短的草的长度

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))#define abs(x) ((x) < 0 ? -1 * (x) : (x))template
inline void swap(T &x, T &y){ T tmp = x;x = y, y = tmp;} template
inline void read(T &x){ x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9') c = ch, ch = getchar(); while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); if(c == '-') x = -x;}const int INF = 0x3f3f3f3f;const int MAXN = 1000000 + 10;long long n,m,a[MAXN],d[MAXN],b[MAXN];struct Node{ //区间内最晚的最近一次被割的草被割时间为last,到last时间区间内草长度和sum //lazy表示区间是否被割 //mi表示到last时间最短的草的长度 long long sum, last, mi; int lazy; int l,r; Node(){l = r = -1;lazy = sum = last = mi = 0;}}node[MAXN << 2];void pushdown(int o){ if(node[o].lazy) { node[o << 1].last = node[o << 1 | 1].last = node[o].last; long long tmp = node[o].sum / (node[o].r - node[o].l + 1); node[o << 1].sum = tmp * (node[o << 1].r - node[o << 1].l + 1); node[o << 1 | 1].sum = tmp * (node[o << 1 | 1].r - node[o << 1 | 1].l + 1); node[o << 1].lazy = node[o << 1 | 1].lazy = 1; node[o << 1].mi = node[o << 1 | 1].mi = tmp; node[o].lazy = 0; }} Node merge(Node x,Node y){ if(x.l == -1) return y; if(y.l == -1) return x; Node re; re.l = x.l, re.r = y.r; if(x.last > y.last) swap(x, y); re.mi = x.mi + (y.last - x.last) * (a[x.l] - a[x.l - 1]); re.sum = x.sum + y.sum + (y.last - x.last) * (a[x.r] - a[x.l - 1]); re.last = y.last; return re;}void build(int o = 1, int l = 1, int r = n){ node[o].l = l, node[o].r = r; if(l == r) return; int mid = (l + r) >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r);}void modify(int ll, int rr, int k, int o = 1, int l = 1, int r = n){ pushdown(o); if(ll <= l && rr >= r) { node[o].lazy = 1; node[o].last = d[k], node[o].sum = b[k] * (node[o].r - node[o].l + 1), node[o].mi = b[k]; return; } int mid = (l + r) >> 1; if(mid >= ll) modify(ll, rr, k, o << 1, l, mid); if(mid < rr) modify(ll, rr, k, o << 1 | 1, mid + 1, r); node[o] = merge(node[o << 1], node[o << 1 | 1]); return;}Node ask(int ll, int rr, int o = 1, int l = 1, int r = n){ pushdown(o); if(ll <= l && rr >= r) return node[o]; int mid = (l + r) >> 1; Node a,b; if(mid >= ll) a = ask(ll, rr, o << 1, l, mid); if(mid < rr) b = ask(ll, rr, o << 1 | 1, mid + 1, r); node[o] = merge(node[o << 1], node[o << 1 | 1]); Node re = merge(a, b); return re;}int find(int k, int o = 1, int l = 1, int r = n){ pushdown(o); if(l == r) { if(b[k] <= node[o].mi + (a[node[o].l] - a[node[o].l - 1]) * (d[k] - node[o].last)) return l; else return -1; } int mid = (l + r) >> 1,re; if(node[o << 1 | 1].mi + (a[node[o << 1 | 1].l] - a[node[o << 1 | 1].l - 1]) * (d[k] - node[o << 1 | 1].last) >= b[k]) { re = mid + 1; int tmp = find(k, o << 1, l, mid); if(tmp != -1) re = tmp; } else re = find(k, o << 1 | 1, mid + 1, r); node[o] = merge(node[o << 1], node[o << 1 | 1]); return re;}std::string s;int stack[1000],top;int main(){ read(n), read(m); register int i; n -= 4; for(i = 1;i <= n;i += 4) { read(a[i]); read(a[i + 1]); read(a[i + 2]); read(a[i + 3]); } n += 4; for(;i <= n;++ i) read(a[i]); std::sort(a + 1, a + 1 + n); n -= 4; for(i = 1;i <= n;i += 4) { a[i] += a[i - 1]; a[i + 1] += a[i]; a[i + 2] += a[i + 1]; a[i + 3] += a[i + 2]; } n += 4; for(;i <= n;++ i)a[i] += a[i - 1]; m -= 4; for(i = 1;i <= m;i += 4) { read(d[i]), read(b[i]); read(d[i + 1]), read(b[i + 1]); read(d[i + 2]), read(b[i + 2]); read(d[i + 3]), read(b[i + 3]); } m += 4; for(;i <= m;++ i) read(d[i]), read(b[i]); build(); for(i = 1;i <= m;++ i) { int ans = 0; Node tmp; ans = find(i); if(ans <= 0) { s += '0'; s += '\n'; continue; } tmp = ask(ans, n); long long tmp2 = tmp.sum + (a[n] - a[ans - 1]) * (d[i] - tmp.last) - (n - ans + 1) * b[i]; char c;top = 0; if(tmp2 == 0) s += '0'; while(tmp2) stack[++ top] = tmp2%10, tmp2 /= 10; while(top) s += stack[top --] + '0'; s += '\n'; modify(ans, n, i); } std::cout << s; return 0;}

转载于:https://www.cnblogs.com/huibixiaoxing/p/8468990.html

你可能感兴趣的文章
音乐网站开发建设定制,手机版DJ音乐网站制作
查看>>
Python学习:Mysql(二)
查看>>
QTP提示加载数据表文件时出错的解决方案
查看>>
VS2010 发布网站总是连同cs文件一起发布了
查看>>
python包管理工具pip
查看>>
async与defer
查看>>
勿施于人之己所不欲
查看>>
asp.net中runat="server"的含义
查看>>
Struts2的OGNL标签详解
查看>>
jquery access方法 有什么用
查看>>
4.XXE (XML External Entity Injection)
查看>>
大白话5分钟带你走进人工智能-第二十四节决策树系列之分裂流程和Gini系数评估(3)...
查看>>
ubuntu下vim与系统剪切板互相拷贝
查看>>
01_Java语言基础部分(数据类型与表达式、流程控制语句、数组与方法)
查看>>
Codeforces Round #248 (Div. 2) B. Kuriyama Mirai's Stones
查看>>
《30天自制操作系统》学习笔记--第好多天
查看>>
CodeForces 617 E. XOR and Favorite Number
查看>>
在spring boot中打印mybaits执行的sql
查看>>
用动态规划解小朋友分糖问题
查看>>
tomcat ----> 启动,关闭和配置等等
查看>>