1. 程式人生 > >HNOI2017 影魔

HNOI2017 影魔

Link

Diffculty

演算法難度6,思維難度7,程式碼難度6

Description

給定一個長度為 n n 的排列 A A

對於一個區間 [

L , R ] ( L < R ) [L,R](L<R)
,如果 m a x ( A L + 1
, A L + 2 , , A R 1 ) < m i n ( A L , A R ) max(A_{L+1},A_{L+2},…,A_{R-1})<min(A_L,A_R)
,那麼它的價值為 p 1 p1

如果 m a x ( A L + 1 , A L + 2 , , A R 1 ) max(A_{L+1},A_{L+2},…,A_{R-1}) 小於 A L A_L A R A_R 中的其中一個,那麼它的價值為 p 2 p2

否則區間價值為 0 0

m m 個詢問,給定 [ a , b ] [a,b] ,詢問 a L < b , a < R b a\le L<b,a<R\le b 的所有區間價值和。

1 n , m 2 × 1 0 5 , 1 p 1 , p 2 1000 1\le n,m\le 2\times 10^5,1\le p1,p2\le 1000

Solution

神仙題。。。

我們考慮把每個區間放在它的最大值處統計。

首先我們求出第 i i 個數左右邊第一個大於它的值的位置 L e f t i , R i g h t i Left_i,Right_i

那麼區間 [ L e f t i , R i g h t i ] [Left_i,Right_i] 滿足 p 1 p1 的價值。

假如固定左端點的話,區間 [ L e f t i , k ] , i < k < R i g h t i [Left_i,k],i<k<Right_i 都滿足 p 2 p2 了。

同理 [ k , R i g h t i ] , L e f t i < k < i [k,Right_i],Left_i<k<i 也都滿足 p 2 p2 了。

我們考慮一旦左端點越過 L e f t i Left_i ,那麼就不符合把區間放在最大值處統計了,右端點同理。

這樣我們可以做到統計所有合法區間而且不統計不合法區間,也就是不重不漏了。

現在,我們考慮如何利用推出的這些東西來計算答案。

我們考慮建立二維平面, ( x , y ) (x,y) 這個點代表 [ x , y ] [x,y] 這個區間。

那麼上面的那三個部分就都可以表示為點或者線段了。

詢問則可以表示為一個正方形。

我們可以兩遍掃描線+線段樹出解。

時間複雜度 O ( n l o g n ) O(nlogn)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
inline int read(){
	int x=0,f=1;char ch=' ';
	while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9')x=x*10+(ch^48),ch=getchar();
	return f==1?x:-x;
}
const int N=2e5+5;
LL sum[N<<2],add[N<<2],Len[N<<2];
inline void pushdown(int rt){
	if(add[rt]){
		sum[rt<<1]+=add[rt]*Len[rt<<1];
		sum[rt<<1|1]+=add[rt]*Len[rt<<1|1];
		add[rt<<1]+=add[rt];
		add[rt<<1|1]+=add[rt];
		add[rt]=0;
	}
}
inline void build(int rt,int l,int r){
	Len[rt]=r-l+1;
	sum[rt]=add[rt]=0;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
}
inline void modify(int rt,int l,int r,int L,int R,int v){
	if(L>R)return;
	if(L<=l && r<=R){
		sum[rt]+=v*Len[rt];
		add[rt]+=v;
		return;
	}
	pushdown(rt);
	int mid=(l+r)>>1;
	if(L<=mid)modify(rt<<1,l,mid,L,R,v);
	if(mid+1<=R)modify(rt<<1|1,mid+1,r,L,R,v);
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline LL query(int rt,int l,int r,int L,int R){
	if(L<=l && r<=R)return sum[rt];
	pushdown(rt);
	int mid=(l+r)>>1;LL ans=0;
	if(L<=mid)ans+=query(rt<<1,l,mid,L,R);
	if(mid+1<=R)ans+=query(rt<<1|1,mid+1,r,L,R);
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
	return ans;
}

struct data{
	int id,x,y1,y2,v;
	inline bool operator < (const data& b) const {
		if(x==b.x)return id<b.id;
		return x<b.x;
	}
}q[N<<2],q2[N<<2];
LL ans[N],p1,p2;
int n,m,cnt,cnt2;
int a[N],Log[N],st[N][18];
int Left[N],Right[N];
int main(){
	n=read();m=read
            
           

相關推薦

Bzoj4826 [Hnoi2017]

起點 攻擊 color output names [1] cmp 攻擊力 otl Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 425 Solved: 244 Description 影魔,奈文摩爾,據說有著一個詩

BZOJ4826: [Hnoi2017]

mem 上下 cnblogs http 最大值 clu memory www 自己的 4826: [Hnoi2017]影魔 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 550 Solved: 300[Submit]

[AH/HNOI2017]

clu 題目 情況 組成 自己 英雄 push 輸出 align 題目背景 影魔,奈文摩爾,據說有著一個詩人的靈魂。 事實上,他吞噬的詩人靈魂早已成千上萬。 千百年來,他收集了各式各樣的靈魂,包括詩人、 牧師、 帝王、 乞丐、 奴隸、 罪人,當然,還有英雄。 題目描述

[HNOI2017]

小結 eve == sca 端點 部分 自然 要求 names 標簽:線段樹 題解:   首先對於題目的條件進行分析,p1的條件是一個區間的兩個端點必須是這一個區間的最大與次大值。p2的條件是一個區間的一個端點是最大值,而另一個端點不是次大值。顯然,他們都需要兩個條件(

HNOI2017

init 位置 truct pan void fin node 左右 按順序 影魔 這麽簡單的方法盡然想不到,我是真的菜 對每個點,用單調棧的方式處理出他左右第一個比他大的數的位置,你可以把\(0\)和\(n+1\)設成\(inf\)。 顯然對於每對\(lef[i]\)和

BZOJ4826 [Hnoi2017] 【線段樹 + 單調棧】

getchar using clas urn 端點 鏈接 push std Go 題目鏈接 BZOJ4826 題解 蒟蒻智力水平捉急orz 我們會發現相鄰的\(i\)和\(j\)貢獻一定是\(p1\),可以很快算出來【然而我一開始忘了考慮調了半天】 我們現在只考慮不相鄰的

[BZOJ4826][HNOI2017] 可持久化線段樹

連結 題意:給你 \(1\) 到 \(n\) 的排列 \(k_1,k_2,\dots,k_n\) ,對 \(i,j (i<j)\)來說,若不存在 \(k_s (i<s<j)\) 大於 \(k_i\) 或者 \(k_j\),則會產生 \(p_1\) 的貢獻。另一種情

[HNOI2017]

Description Portal 一句話題意:給定n個數的排列,m次詢問,每次詢問詢問一個區間內所有子區間的貢獻。 每個區間如果兩個端點分別是最大值和次大值,我們就算P1的貢獻。 如果兩個端點一個是最大值,一個不是次大值,我們就算P2的貢獻。 $ n, m \leq 200009 $ Soluti

[AH2017/HNOI2017]

P3722 [AH2017/HNOI2017]影魔 題解: 法一: [bzoj4826][HNOI2017]影魔 直接轉化成區間內單點的貢獻, 分開p1,p2考慮 而min(ai,aj),max(ai,aj)要考慮固定一個點、 對於p1,固定i為較小值。發現,這個j只有L[i]或R[i]滿足。

luogu P3722 [AH2017/HNOI2017]

傳送門 我太弱了,只會亂搞,正解是不可能正解的,這輩子不可能寫正解的,太蠢了又想不出什麼東西,就是亂搞這種東西,才能維持得了做題這樣子 考慮將詢問離線,按右端點排序,並且預處理出每個位置往前面第一個大於這個數的位置,記為\(fa_i\) 如果加入一個右端點\(i\),那麼可以加上貢獻的左端點有以下三類

HNOI2017

Link Diffculty 演算法難度6,思維難度7,程式碼難度6 Description 給定一個長度為 n n

[bzoj4826][HNOI2017]

題目描述 影魔,奈文摩爾,據說有著一個詩人的靈魂。事實上,他吞噬的詩人靈魂早已成千上萬。千百年來,他收集了各式各樣 的靈魂,包括詩人、牧師、帝王、乞丐、奴隸、罪人,當然,還有英雄。每一個靈魂,都有著自己的戰鬥力,而影魔,靠 這些戰鬥力提升自己的攻擊。奈文摩

[HNOI2017] bzoj 4826 - 線段樹 - 掃描線 - 單調棧

題目大意:給一個排列p,多次詢問一個區間[l,r]的中有多少子區間[i,j]滿足: m x (

[HNOI2017] bzoj 4826

題目大意:給一個排列p,多次詢問一個區間[l,r]的中有多少子區間[i,j]滿足: mx(i+1,j−1)≤min(p[i],p[j])mx(i+1,j-1)\le min(p[i],p[j])mx(i+1,j−1)≤min(p[i],p[j])(記做cnt1)

[BZOJ 4826] 區間修改主席樹 標記永久化

brush sca ostream www cpp pad stream i+1 return 為了這道題還特地去學了標記永久化,可能對於區間修改主席樹或者樹套樹比較有用吧OvO 我們可以把答案分為兩部分:p1造成的和p2造成的 我們枚舉序列,用單調棧求出序列每一個位置

[HNOI 2017]

operator 之間 www. 一段 掃描 隊列 urn blog scan Description 題庫鏈接 給你一段長度為 \(n\) 的序列 \(K\) 。 \(m\) 組詢問,每次給定左右端點 \(l,r\) 。求出滿足區間內下述貢獻和。 如果一個區間的兩個端點

[bzoj4826][亂搞][樹狀陣列]

Description 影魔,奈文摩爾,據說有著一個詩人的靈魂。事實上,他吞噬的詩人靈魂早已成千上萬。千百年來,他收集了各式各樣 的靈魂,包括詩人、牧師、帝王、乞丐、奴隸、罪人,當然,還有英雄。每一個靈魂,都有著自己的戰鬥力,而影魔,靠 這些戰鬥力提升自己的攻擊。奈文摩爾有

BZOJ 4827 [Hnoi2017]禮物 ——FFT

最小 sharp scan con 禮物 struct swa 1.0 -i 題目上要求一個循環卷積的最小值,直接破環成鏈然後FFT就可以了。 然後考慮計算的式子,可以分成兩個部分分開計算。 前半部分FFT,後半部分掃一遍。 #include <map> #i

《摔跤吧,爸爸》觀筆記

兩個 自己的 分享 傷感 生產 眼神 青年 打了 src 印度片,阿米爾汗的片子。主要人物: 馬哈維亞,吉塔,巴比塔,他們的教練(反角),他們的表哥,賣雞蛋的劇情概要: 馬哈維爾是印度的前全國冠軍摔跤手,他曾經拿過全國的總冠軍,然後迫於生計,只好轉行,放棄了自己

慢慢來臨,成個伸長手臂撲嚟嘅

mem 一聲 萬全 依然 html 平安 意思 救世主 崩潰 夜麻麻,喺日頭嘅喧囂中慢慢來臨,成個伸長手臂撲嚟嘅魔鬼噉,顯得啲噉嘅恐怖猙獰。明亮嘅閨房內,一位絕世佳人優雅端莊嘅彈著琴曲,好睇嘅眉頭就與明月光青梅竹馬,王上都有將明月光許配畀秦凡嘅諗法。十歲嗰年,秦凡出征日族,