[문제 풀이] bzoj 4540 HNOI 2016 시퀀스
주어진 길이 n 의 시퀀스: a1, a2,..., an, a [1: n] 로 기록 합 니 다.유사 하 게 a [l: r] (1 ≤ l ≤ r ≤ N) 는 서열: al, al + 1,..., ar - 1, ar 를 가리킨다.만약 1 ≤ l ≤ s ≤ t ≤ r ≤ n 이 라면 a [s: t] 는 a [l: r] 의 하위 서열 이 라 고 부른다.현재 q 개의 질문 이 있 습 니 다. 각 질문 은 두 개의 수 l 과 r, 1 ≤ l ≤ r ≤ n 을 정 하고 a [l: r] 의 서로 다른 하위 서열 의 최소 값 의 합 을 구 합 니 다.예 를 들 어 주어진 서열 은 5, 2, 4, 1, 3 이 고 주어진 두 개의 수 는 1 과 3 이 라 고 묻는다. 그러면 a [1: 3] 는 6 개의 서열 a [1: 1], a [2: 2], a [3: 3], a [2: 3], a [1: 3] 가 있 는데 이 6 개의 서열 의 최소 치 의 합 은 5 + 2 + 4 + 2 + 2 + 2 = 17 이다.
Input
입력 파일 의 첫 줄 은 두 개의 정수 n 과 q 를 포함 하고 각각 시퀀스 길이 와 문의 수 를 대표 합 니 다.다음 줄 은 n 개의 정 수 를 포함 하고 빈 칸 으로 구분 하 며 i 의 정 수 는 ai, 즉 서열 i 의 요소 의 값 입 니 다.다음 q 줄 은 줄 마다 두 개의 정수 l 과 r 를 포함 하고 한 번 의 질문 을 대표 합 니 다.
Output
매번 질문 할 때마다 한 줄 을 출력 하 는 것 은 질문 의 답 을 대표 합 니 다.
Sample Input
5 5 5 2 4 1 3 1 5 1 3 2 4 3 5 2 5
Sample Output
28 17 11 11 17
HINT
1 ≤N,Q ≤ 100000,|Ai| ≤ 10^9
Solution
서열 중의 어떤 숫자 인 Ai 를 고려 하여 왼쪽 의 첫 번 째 작은 숫자 를 기억 하 는 위 치 는 lasti (없 으 면 0) 이 고 오른쪽 에 있 는 첫 번 째 작은 숫자 를 기억 하 는 위 치 는 nexti (없 으 면 n + 1) 입 니 다.우 리 는 이 수가 공헌 한 구간 의 왼쪽 단점 범 위 는 [lasti + 1, i] 이 고 오른쪽 단점 범 위 는 [i, nexti - 1] 임 을 알 수 있다.그래서 우 리 는 한 수의 공헌 범 위 를 평면 위의 사각형 으로 볼 수 있다. 이 평면의 가로 좌 표 는 특정한 구간 의 왼쪽 단점 을 대표 하고 세로 좌 표 는 특정한 구간 의 오른쪽 단점, 즉 평면 상의 점 (L, R) 은 구간 [L, R] 을 대표 한다.그래서 Ai 에 있어 그의 공헌 범 위 는 평면 적 으로 가로 좌표 가 [lasti + 1, i] 이 고 세로 좌 표 는 [i, nexti - 1] 범위 내의 사각형 구역 이다.또한 하나의 질문 [L, R] 에 대해 가로 좌표 가 L 보다 크 고 세로 좌표 가 R 보다 작은 사각형 구역 을 묻 는 것 입 니 다 (우 리 는 기본 평면 에서 R > L 의 지역 공헌 은 0 입 니 다).그래서 문 제 는 우리 에 의 해 평면 사각형 덧셈, 평면 사각형 조회 가중치 와 문제 로 바 뀌 었 다.이것 은 오프라인 + 스캐닝 라인 을 트 리 배열 / 선분 트 리 로 O (nlog2n) 시간 내 에 완성 할 수 있 습 니 다.
평면 사각형 덧셈, 평면 사각형 조회 가중치 와 문제 에 대해 우 리 는 y 에 따라 어 릴 때 부터 대청소 합 니 다.현재 스캐닝 라인 의 높이 는 H 이 고 사각형 의 상 계 는 up 이 며 사각형 의 하 계 는 down 이 며 왼쪽 은 L 이 고 오른쪽 은 R 이 며 현재 사각형 의 가중치 는 val 입 니 다.만약 에 현재 사각형 이 상계 까지 쓸 리 지 않 았 다 면 그 는 가로 좌표 [L, R] 범위 내 에서 모든 점 의 공헌 은 (H - down) * 8727 ° val = H * 8727 ° val - down * 8727 ° val 이다. 우 리 는 두 개의 나무 모양 배열 / 선분 나무 로 각각 가로 좌표 에 있 는 val 과 down * 8727 ° val 을 유지 하고 조회 할 때 하 나 를 곱 하고 하 나 를 더 하 는 것 은 k * 8727 ° H + b 의 형식 이다.즉, 첫 번 째 트 리 배열 에서 모든 가로 세로 표 시 는 현재 H 의 k 값 을 유지 하고 두 번 째 는 b 값 을 유지 합 니 다.현재 사각형 이 상계 로 쓸 어 올 리 고 곧 물 러 날 것 입 니 다. 그러면 그 는 앞으로 가로 좌표 [L, R] 범위 내 에서 모든 점 의 공헌 이 (up - down) * 8727 ° val 입 니 다. 이 공헌 은 더 이상 변 하지 않 기 때문에 우 리 는 이 공헌 을 두 번 째 트 리 / 라인 트 리 에 추가 하여 유지 하고 첫 번 째 라인 트 리 의 val 을 삭제 하면 됩 니 다.
코드:
#include
#include
#include
using namespace std;
template<typename T>inline void read(T &x){
T f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(x=0;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
typedef long long LL;
const int maxn=100010;
int n,m,a[maxn],L[maxn],R[maxn],cnt,sta[maxn],top;
LL ans[maxn];
struct Line{
int l,r,y,f,id;
bool operatorconst{
if(y==b.y)return freturn y2];
struct Bit{
LL a[maxn],b[maxn];
Bit(){
memset(a,0,sizeof a);
memset(b,0,sizeof b);
}
void Add(int x,LL val){
for(int i=x;i<=n;i+=(i&-i))
a[i]+=val,b[i]+=val*x;
}
void Add(int l,int r,LL val){
Add(l,val);Add(r+1,-val);
}
LL Query(int x){
LL ans=0;
for(int i=x;i;i-=(i&-i))
ans+=a[i]*(x+1)-b[i];
return ans;
}
LL Query(int l,int r){
return Query(r)-Query(l-1);
}
}k,b;
int main(){
read(n);read(m);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<=n;i++){
while(top&&a[sta[top]]>=a[i])top--;
top++;L[sta[top]=i]=sta[top-1];
}
sta[top=0]=n+1;
for(int i=n;i>=1;i--){
while(top&&a[sta[top]]>a[i])top--;
top++;R[sta[top]=i]=sta[top-1];
}
for(int i=1;i<=m;i++){
read(q[i].l),read(q[i].y);
q[i].r=q[i].l;q[i].f=1;q[i].id=i;
}
cnt=m;
for(int i=1;i<=n;i++){
q[++cnt].l=L[i]+1;q[cnt].f=0;
q[cnt].r=i;q[cnt].y=i;q[cnt].id=i;
q[++cnt].l=L[i]+1;q[cnt].f=2;
q[cnt].r=i;q[cnt].y=R[i]-1;q[cnt].id=i;
}
sort(q+1,q+cnt+1);
for(int i=1;i<=cnt;i++){
if(!q[i].f){
k.Add(q[i].l,q[i].r,a[q[i].id]);
b.Add(q[i].l,q[i].r,(LL)a[q[i].id]*(1-q[i].id));
}
else if(q[i].f==2){
k.Add(q[i].l,q[i].r,-a[q[i].id]);
b.Add(q[i].l,q[i].r,(LL)a[q[i].id]*q[i].y);
}
else ans[q[i].id]=k.Query(q[i].l,n)*q[i].y+b.Query(q[i].l,n);
}
for(int i=1;i<=m;i++)printf("%lld
",ans[i]);
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.