BZOJ4889: [TJOI2017]不勤劳的图书管理员
额,这个题由于被卡评测了,于是变成了权限题。。。
本蒟蒻表示没钱氪金。。。
当然,可以去洛谷/LOJLOJ搞搞事。。。
这里附上洛谷的题面。
题目描述
加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员。他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度。现在有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后输出
输入输出样例
说明
对于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!
首先,题目可以转化为:
- 区间询问关键字<x<x的元素个数,和这些元素的valval之和。
- 单点修改。
对某一本书统计厌烦度时只需这么统计:ans+=给它作出贡献的书的总页数+给它作出贡献的书的个数×自己的页数
然后这个显然树套树维护。
我用了树状数组套动态开点权值线段树。
网上还有分块套树状数组的题解,太神了。。。
本蒟蒻好菜啊。。。
附代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #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; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?