BZOJ4889: [TJOI2017]不勤勞的圖書管理員

BZOJ4889: [TJOI2017]不勤勞的圖書管理員php

額,這個題因爲被卡評測了,因而變成了權限題。。。ios

本蒟蒻表示沒錢氪金。。。數組

固然,能夠去洛谷/$LOJ$搞搞事。。。ide

洛谷P3759 [TJOI2017]不勤勞的圖書管理員spa

LOJ#2639. 「TJOI2017」不勤勞的圖書管理員blog

這裏附上洛谷的題面。get

題目描述

加里敦大學有個帝國圖書館,小豆是圖書館閱覽室的一個書籍管理員。他的任務是把書排成有序的,因此無序的書讓他產生厭煩,兩本亂序的書會讓小豆產生這兩本書頁數的和的厭煩度。如今有n本被打亂順序的書,在接下來m天中天天都會由於讀者的閱覽致使書籍順序改變位置。由於小豆被要求在接下來的m天中至少要整理一次圖書。小豆想知道,若是他前i天不去整理,第i天他的厭煩度是多少,這樣他好選擇厭煩度最小的那天去整理。it

輸入輸出格式

輸入格式:io

 

第一行會有兩個數,n,m分別表示有n本書,m天class

接下來n行,每行兩個數,ai和vi,分別表示第i本書原本應該放在ai的位置,這本書有vi頁,保證不會有放置同一個位置的書

接下來m行,每行兩個數,xj和yj,表示在第j天的第xj本書會和第yj本書會由於讀者閱讀交換位置

 

輸出格式:

 

一共m行,每行一個數,第i行表示前i天不去整理,第i天小豆的厭煩度,由於這個數可能很大,因此將結果模10^9 +7後輸出

 

輸入輸出樣例

輸入樣例#1:  複製
5 5
1 1
2 2
3 3
4 4
5 5
1 5
1 5
2 4
5 3
1 3
輸出樣例#1:  複製
42
0
18
28
48

說明

對於20%的數據,1 ≤ ai; xj; yj ≤ n ≤ 5000, m ≤ 5000, vi ≤ 10^5

對於100%的數據,1 ≤ ai; xj; yj ≤ n ≤ 50000, m ≤ 50000, vi ≤ 10^5


題解Here!

首先,題目能夠轉化爲:

  1. 區間詢問關鍵字$<x$的元素個數,和這些元素的$val$之和。
  2. 單點修改。

對某一本書統計厭煩度時只需這麼統計:$$ans+=\text{給它做出貢獻的書的總頁數}+\text{給它做出貢獻的書的個數}\times\text{本身的頁數}$$

而後這個顯然樹套樹維護。

我用了樹狀數組套動態開點權值線段樹。

網上還有分塊套樹狀數組的題解,太神了。。。

本蒟蒻好菜啊。。。

附代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 50010
#define MOD 1000000007LL
using namespace std;
int n,m;
long long ans=0;
int root[MAXN];
struct Book{
	int x,val;
}book[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline int lowbit(int x){return x&(-x);}
namespace BIT{
	long long s[MAXN],sum[MAXN];
	inline void add(int x,long long v){for(;x<=n;x+=lowbit(x)){s[x]++;sum[x]+=v;}}
	inline long long get_num(int x){long long ans=0;for(;x;x-=lowbit(x))ans+=s[x];return ans;}
	inline long long get_sum(int x){long long ans=0;for(;x;x-=lowbit(x))ans+=sum[x];return ans;}
}
namespace ST{
	#define LSON(rt) a[rt].lson
	#define RSON(rt) a[rt].rson
	#define SUM(rt) a[rt].sum
	#define DATA(rt) a[rt].data
	int size=0;
	struct Segment_Tree{
		long long sum;
		int data,lson,rson;
	}a[MAXN<<8];
	void update(int k,int v,int c,int lside,int rside,int &rt){
		if(!rt)rt=++size;
		DATA(rt)+=c;SUM(rt)+=v;
		if(lside==rside)return;
		int mid=lside+rside>>1;
		if(k<=mid)update(k,v,c,lside,mid,LSON(rt));
		else update(k,v,c,mid+1,rside,RSON(rt));
	}
	long long query_num(int l,int r,int lside,int rside,int rt){
		if(!rt)return 0;
		long long ans=0;
		if(l<=lside&&rside<=r)return DATA(rt);
		int mid=lside+rside>>1;
		if(l<=mid)ans+=query_num(l,r,lside,mid,LSON(rt));
		if(mid<r)ans+=query_num(l,r,mid+1,rside,RSON(rt));
		return ans;
	}
	long long query_sum(int l,int r,int lside,int rside,int rt){
		if(!rt)return 0;
		long long ans=0;
		if(l<=lside&&rside<=r)return SUM(rt);
		int mid=lside+rside>>1;
		if(l<=mid)ans+=query_sum(l,r,lside,mid,LSON(rt));
		if(mid<r)ans+=query_sum(l,r,mid+1,rside,RSON(rt));
		return ans;
	}
}
inline void update(int x,int k,int v,int c){for(;x<=n;x+=lowbit(x))ST::update(k,v,c,1,n,root[x]);}
inline long long query_num(int x,int y,int l,int r){
	if(x>y||l>r)return 0;
	long long ans=0;
	for(;y;y-=lowbit(y))ans+=ST::query_num(l,r,1,n,root[y]);
	for(--x;x;x-=lowbit(x))ans-=ST::query_num(l,r,1,n,root[x]);
	return ans;
}
inline long long query_sum(int x,int y,int l,int r){
	if(x>y||l>r)return 0;
	long long ans=0;
	for(;y;y-=lowbit(y))ans+=ST::query_sum(l,r,1,n,root[y]);
	for(--x;x;x-=lowbit(x))ans-=ST::query_sum(l,r,1,n,root[x]);
	return ans;
}
void work(){
	int x,y;
	while(m--){
		x=read();y=read();
		if(x==y){
			printf("%lld\n",ans);
			continue;
		}
		if(x>y)swap(x,y);
		
		//--------------------------------------------------------------------------------
		
		ans=(ans+query_sum(x+1,y-1,1,book[y].x-1)%MOD+query_num(x+1,y-1,1,book[y].x-1)*book[y].val%MOD)%MOD;
		ans=((ans-query_sum(x+1,y-1,book[y].x+1,n)%MOD+MOD)%MOD-query_num(x+1,y-1,book[y].x+1,n)*book[y].val%MOD+MOD)%MOD;
		
		//--------------------------------------------------------------------------------
		
		ans=(ans+query_sum(x+1,y-1,book[x].x+1,n)%MOD+query_num(x+1,y-1,book[x].x+1,n)*book[x].val%MOD)%MOD;
		ans=((ans-query_sum(x+1,y-1,1,book[x].x-1)%MOD+MOD)%MOD-query_num(x+1,y-1,1,book[x].x-1)*book[x].val%MOD+MOD)%MOD;
		
		//--------------------------------------------------------------------------------
		
		if(book[x].x>book[y].x)ans=(ans-book[x].val-book[y].val+MOD)%MOD;
		else ans=(ans+book[x].val+book[y].val)%MOD;
		
		//--------------------------------------------------------------------------------
		
		update(x,book[x].x,-book[x].val,-1);update(y,book[y].x,-book[y].val,-1);
		swap(book[x].x,book[y].x);swap(book[x].val,book[y].val);
		update(x,book[x].x,book[x].val,1);update(y,book[y].x,book[y].val,1);
		
		//--------------------------------------------------------------------------------
		
		printf("%lld\n",ans);
	}
}
void init(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		book[i].x=read();book[i].val=read();
		update(i,book[i].x,book[i].val,1);
	}
	for(int i=n;i>=1;i--){
		BIT::add(book[i].x,book[i].val);
		ans=(ans+BIT::get_sum(book[i].x-1)%MOD+BIT::get_num(book[i].x-1)*book[i].val%MOD)%MOD;
	}
}
int main(){
	init();
	work();
    return 0;
}
相關文章
相關標籤/搜索