BZOJ4889: [TJOI2017]不勤劳的图书管理员

BZOJ4889: [TJOI2017]不勤劳的图书管理员

额,这个题由于被卡评测了,于是变成了权限题。。。

本蒟蒻表示没钱氪金。。。

当然,可以去洛谷/$LOJ$搞搞事。。。

洛谷P3759 [TJOI2017]不勤劳的图书管理员

LOJ#2639. 「TJOI2017」不勤劳的图书管理员

这里附上洛谷的题面。

题目描述

加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员。他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度。现在有n本被打乱顺序的书,在接下来m天中每天都会因为读者的阅览导致书籍顺序改变位置。因为小豆被要求在接下来的m天中至少要整理一次图书。小豆想知道,如果他前i天不去整理,第i天他的厌烦度是多少,这样他好选择厌烦度最小的那天去整理。

输入输出格式

输入格式:

 

第一行会有两个数,n,m分别表示有n本书,m天

接下来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;
}

 

posted @ 2018-09-13 21:21  符拉迪沃斯托克  阅读(304)  评论(0编辑  收藏  举报
Live2D