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後輸出
對於20%的數據,1 ≤ ai; xj; yj ≤ n ≤ 5000, m ≤ 5000, vi ≤ 10^5
對於100%的數據,1 ≤ ai; xj; yj ≤ n ≤ 50000, m ≤ 50000, vi ≤ 10^5
首先,題目能夠轉化爲:
對某一本書統計厭煩度時只需這麼統計:$$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; }