BZOJ2141: 排队

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2141

分块加树状数组。

离散化之后,每一个块建一个树状数组。交换x,y,与x左边的数和y右边的数无关,只需处理>x,<y的数。

话说还可以用树套树来写,不过常数太大,比分块加树状数组慢。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define inf 1<<30
 7 #define maxn 20005
 8 using namespace std;
 9 int n,m,nn,tot,ans,a[maxn],t[205][maxn];
10 struct fuck{int x,id;}c[maxn];
11 int read(){
12     int x=0,f=1; char ch;
13     for(ch=getchar();ch<‘0‘||ch>‘9‘;ch=getchar()) if(ch==‘-‘) f=-1;
14     for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘;
15     return x*f;
16 }
17 bool comp(fuck a,fuck b){return a.x<b.x;}
18 int p(int x){return (x-1)/nn+1;}
19 void change(int f,int x,int y){for(int i=x;i<=tot;i+=i&-i) t[f][i]+=y;}
20 int query(int f,int x){int y=0;for(int i=x;i;i-=i&-i) y+=t[f][i];return y;}
21 int main(){
22     n=read(); nn=sqrt(n);
23     for(int i=1;i<=n;i++) c[i].x=read(),c[i].id=i;
24     sort(c+1,c+n+1,comp);
25     for(int i=1;i<=n;i++){
26         if(c[i].x!=c[i-1].x) ++tot;
27         a[c[i].id]=tot;
28     }
29     for(int i=n;i;i--){
30         ans+=query(0,a[i]-1);
31         change(0,a[i],1);
32     }
33     printf("%d\n",ans);
34     for(int i=1;i<=n;i++) change(p(i),a[i],1);
35     m=read();
36     int x,y;
37     while(m--){
38         x=read(); y=read(); if(x>y) swap(x,y);
39         for(int i=p(x)+1;i<p(y);i++){
40             ans-=query(i,a[x]-1); ans+=query(i,tot)-query(i,a[x]);
41             ans-=query(i,tot)-query(i,a[y]); ans+=query(i,a[y]-1);
42         }
43         for(int i=x+1;p(i)==p(x)&&i<y;i++){
44             if(a[i]<a[x]) ans--; if(a[i]>a[x]) ans++;
45             if(a[i]<a[y]) ans++; if(a[i]>a[y]) ans--;
46         }
47         if(p(x)!=p(y))
48         for(int i=y-1;p(i)==p(y);i--){
49             if(a[i]<a[x]) ans--; if(a[i]>a[x]) ans++;
50             if(a[i]<a[y]) ans++; if(a[i]>a[y]) ans--;
51         }
52         if(a[x]<a[y]) ans++; if(a[x]>a[y]) ans--;
53         change(p(x),a[x],-1); change(p(x),a[y],1);
54         change(p(y),a[y],-1); change(p(y),a[x],1);
55         swap(a[x],a[y]);
56         printf("%d\n",ans);
57     }
58     return 0;
59 }

时间: 2024-10-26 03:46:46

BZOJ2141: 排队的相关文章

[bzoj2141][排队] (分块大法好)

Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观.设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量.幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度.为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度. I

bzoj2141排队(辣鸡但是好写的方法)

题意很明确,也非常经典: 一个支持查询 区间中比k大的数的个数 并且支持单点修改的序列 ——因为题意可以转化为:查询这两个数中比后者大的个数.比后者小的个数.比前者大的个数.比前者小的个数(根据这4个就能算出增加/减少了多少对逆序对)并且把两个数修改掉 于是就出现了 ——来自百度 一个二分就能解决套个卵蛋woc身为一个蒟蒻,表示没有一个写得出的 于是我就想了一个好写(Rank100+几乎T掉)的方法: 首先复制一份原数据,把一份分块,并且保证每一块中的单调(也就是调用sqrt(n)次排序) 然后

bzoj2141: 排队 cdq分治

和动态逆序对有些类似  这题既可以以时间为第一维 也可以以x轴维第一维度   具体视题目而定 cdq分治只能求点对之间的影响  如果要变成整个序列的情况  那么可以用前缀和   一开始的原序列的id设置成0即可 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #

【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树

这个题就是动态偏序对,每次操作做两个删除两个插入就好了. #include<cstdio> #include<iostream> #include<cstring> #define MAXN 100010 using namespace std; typedef long long LL; typedef double D; const D a=0.756; LL ans; struct ScapeGoat_Tree { ScapeGoat_Tree *ch[2]; i

队列练习--排队买饭

题目描述 中午买饭的人特多,食堂真是太拥挤了,买个饭费劲,理工大的小孩还是很聪明的,直接奔政通超市,哈哈,确实,政通超市里面也卖饭,有好几种菜,做的比食堂好吃多了,价格也不比食堂贵,并且买菜就送豆浆,吸引了不少童鞋.所以有时吧,人还是很多的,排队是免不了的,悲剧的是超市只有两个收银窗口. 问题是这样的:开始有两队人在排队,现在咱们只研究第一队,现在我们给每个人一个编号,保证编号各不相同,排在前面的人买完饭就走了,有些人挑完饭就排在后面等待付款,还有一些人比较聪明,看到另一个队人比较少,直接离开这

luogu P1966 火柴排队

二次联通门 : luogu P1966 火柴排队 /* luogu P1966 火柴排队 神TM逆序对... noip怎么这么坑啊.. 暴力都没得打 此题模拟考试时爆了0 做法 将A数组排序,由于B数组与A数组是一一对应的 那么B数组的位置也会发生相应的变化 此时B数组逆序数对数即为答案 */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 123123123; cha

【NOIP2013】火柴排队

P1092 - [NOIP2013]火柴排队 Description Input 共三行,第一行包含一个整数 n,表示每盒中火柴的数目. 第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度. 第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度. Output 输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果. Sample Input 样例1: 4 2 3 1 4 3 2 1 4 样例2: 4 1 3 4 2 1 7 2

节点的排队时延与丢包

节点时延中最复杂和有趣的部分是排队时延\(d_{queue}\).与其他三种时延不同,排队时延对不同的分组是不同的. 在表征排队时延时,通常使用统计量测度,比如平均排队时延.排队时延的方差和排队时延超过某些特定值的概率. 排队时延的决定因素 流量到达该队列的速率\(a\ pkt/s\) 链路的传输速率\(R\ b/s\),即队列中推出比特的速率(不是接收) 到达流量的性质,周期性到达或者以突发形式到达 流量强度与排队时延 假定所有分组都是\(L\)比特组成,且队列无限大,则称\(La/R\)为流

[BZOJ 2729][HNOI2012]排队(排列组合+高精)

Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) Solution 好像必须写压位高精的QAQ 先排n名男生,插空,讨论两名老师插在两个不同的空里的情况和先排在一起再在中间插一名女生的情况 #include<iostream> #include<cstdio> #include<cstring> #include&