2016.6.10测试
2016-06-10 14:01
197 查看
[b]1、汽艇(Boat.cpp/c/pas)[/b]
【问题描述】
有 n 个人要去坐 1 汽艇,每个人单独坐汽艇的快乐程度是 Ci,每多一个人,他的快乐程度会减去 Di,请求出使快乐程度之和达到最大的方案。(假设汽艇的容量足够大)。
【输入格式】
输入文件共有 3 行:
第1 行是一个整数 n;
第2 行有n 个整数,依次表示每个人单独坐汽艇的快乐程度 Ci(1<=Ci<=10000);
第3 行有n 个整数,依次表示每多 1 人,每个人快乐程度的下降值 Di(1<=Di<=10)。
【输出格式】
应输出两行:
第1 行一个整数,是最大的快乐程度之和;
第2 行一个整数,是最大的快乐程度之和所对应的汽艇上的人数(若有多种方案,则输出人数最多的)。
【输入样例】
6
10 10 10 10 10 9
2 2 2 2 2 3
【输出样例】
18
3
【样例说明】
前 3 个人去坐汽艇可使快乐程度之和达到最大,每个人的快乐程度均为 10-2*2=6,总和是
18。
【数据范围】
对于 30%的数据,n<=20;
对于 100%的数据,n<=1000。
正解:贪心
解题报告:
标准水题,枚举有多少个人,然后每次sort,取最优的情况即可。
[b]2、上网(net.cpp/c/pas) [/b]
【问题描述】
假设有 n 个人要上网,却只有 1 台电脑可以上网。上网的时间是从 1 szw 至 T szw ,szw是一个自创的时间单位,至于 szw怎么换算成 s,min 或 h,没有人清楚。依次给出每个人在某个时间段内上网的快乐程度 C(必须这个人在整个时间段内都在上网,才能获得快乐程度C,否则,快乐程度是 0),请你得到使总的快乐程度达到最大的方案。
【输入格式】
第1 行2 个整数 n和 T,含义如题目所述;
接下来有 n 个这样的结构(每两个相邻的结构之间有一空行,且第 1 个结构和第一行间有
一空行):
第1 行一个整数 Mi,表示第 i 个人的时间段的个数;
接下来有 Mi 行,每行3个整数 Xj,Yj,C,表示第 i个人在[Xj,Yj]内上网的快乐程度为 C,
因此有 Xj-Yj-1=1,X1=1,Ymi=T,Xj<=Yj。
【输出格式】
仅输出一行,为总的最大的快乐程度。
【输入样例】
3 10
3
1 3 6
4 7 9
8 10 3
3
1 3 5
4 7 10
8 10 1
4
1 3 2
4 8 2
9 9 6
10 10 3
【输出样例】
25
【样例说明】
在[1,3]内,安排 1 上网,快乐程度为 6;
在[4,7]内,安排 2 上网,快乐程度为 10; 在[8,8]内,不安排;
在[9,9]内,安排 3 上网,快乐程度为 6;
在[10,10]内,安排 3 上网,快乐程度为 3;
这是使总的快乐程度达到最大的方案,对应的值是 25。
【数据范围】
对于 30%的数据,n<=4,所有的 Mi<=5,T<=20;
对于 60%的数据,n<=100,所有的 Mi<=100,T<=2000;
对于 100%的数据,n<=500,所有的 Mi<=500,T<=500000,所有的 0<C<=10^9,并保证最终解 Max<=10^9。
正解:DP
解题报告:
这道题我开始居然想了很久,我真是太菜了。。。
果断DP,每个人的各段区间没有任何区别,直接丢一起按照左端点排序。题目可转化为给定若干带权区间,取出不重叠的区间使权值最大。
貌似大家都是在做区间数的做法。。。我是直接讨论时间,for时间,然后记录一下处理到哪段区间,并且当前的最左端点,一维DP
[b]3、集合(gather)[/b]
【问题描述】
小明总喜欢做一些与众不同的事情,最近他迷上了集合运算。他觉得光是简单的预算不过瘾,所以他把2个集合运算集合起来。由于小明很喜欢区间运算。于是他定义了一个这样的值。
你N个各不相同的区间,请你从中找出若干个区间使其权值最大。
W=|A1∪A2∪……∪AK|*|A1∩A2∩……AK|
其中{A1,A2……AK}(K>1,Ai<>Aj{i<>j})
如果这些区间没有交集则权值为0,给你N个各不相同的区间,请你从中找出若干个区间使其权值最大,并告诉小明。
【输入文件】
第一行N
接下来N行 l r(1<=l<r<=10^6)
【输出文件】
最大权值
【输入样例】
4
1 6
4 8
2 7
3 5
【输出样例】
24
【数据约定】
10% N<=10
30% N<=2*10^4
50% N<=10^5
100% 1<N<=10^6
正解:决策单调性
解题报告:
考场上明明想出来了,一定是两个的时候最优,但是自己不相信自己,而且感觉n^2的暴力也会TLE就没打,打了一个大暴力,水到20分。
等我打完大暴力,心血来潮make数据发现永远是2个的时候最优。。。追悔莫及。。。
显然直接两两枚举会TLE,就要考虑优化。
题解说 用决策单调性,有一些奇奇怪怪的性质。传送门:http://www.cnblogs.com/chenyushuo/p/5261657.html
这道题居然是BZOJ原题,出题人真懒。
先贴一发大暴力:
正解:单调队列+单调栈
[b]4、新斯诺克(snooker.cpp/c/pas)[/b]
【问题描述】
斯诺克又称英式台球,是一种流行的台球运动。在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分别为 1 个白球,15 个红球和 6 个彩球(黄、绿、棕、蓝、粉红、黑)共22个球。击球顺序为一个红球、一个彩球直到红球全部落袋,然后以黄、绿、棕、蓝、粉红、黑的顺序逐个击球,最后以得分高者为胜。斯诺克的魅力还在于可以打防守球, 可以制造一些障碍球使对方无法击打目标球而被扣分。正是因为这样,斯诺克是一项充满神奇的运动。 现在考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为M,台面上有 N 个红球排成一排,每一个红球都有一个标号,`他们的标号代表了他们的分数。 现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K 到红球”。我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球。并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处。每次击打时候,要想“K到红球”,至少要击打一个红球,如果想一次击打多个红球,那么击打的红球必须是依次连续排列的。 如果一次 “K 到红球”所有红球的标号之和的平均数大于母球的标号M,就获得了一个 “连击”。 现在请你计算总共能有多少种“连击”方案。
注意:如果当前有标号为 1、2、3的三种红球,母球标号为 0, 有如下 6 种获得“连击”方案: (1) 、 (2) 、 (3) 、 (1,2) 、 (2,3) 、 (1,2,3)
【输入文件】
输入文件共有两行,第一行是 N,M (N<=100000,M<=10000),
N 表示台面上一共有 N 个红球,M 表示母球的标号。
第二行是 N 个正整数,依次表示台面上 N 个红球的标号,所有标号均不超过10000。
【输出文件】
输出文件只有一个数,为“连击”的方案总数。
【输入样例】
4 3
3 7 2 4
【输出样例】
7
正解:归并排序,逆序对
解题报告:
刚看到这道题就想到POJ上刷的那道求序列的最大平均值的神题,那个是用斜率优化、凸包优化的DP,结果发现跟这道题并没有关系,被小胖犇狠狠嘲讽了一波。
静下心来推导了一波。发现一个神奇的性质:一个区间[i,j]满足条件当且仅当(前缀和)(sum[j]-sum[i-1])/(j-i) > m,移项:(sum[j]-sum[i-1])>(j-i)*m。。。高兴地发现这就是一个逆序对。。。
直接归并排序,求前缀和的逆序对。
【问题描述】
有 n 个人要去坐 1 汽艇,每个人单独坐汽艇的快乐程度是 Ci,每多一个人,他的快乐程度会减去 Di,请求出使快乐程度之和达到最大的方案。(假设汽艇的容量足够大)。
【输入格式】
输入文件共有 3 行:
第1 行是一个整数 n;
第2 行有n 个整数,依次表示每个人单独坐汽艇的快乐程度 Ci(1<=Ci<=10000);
第3 行有n 个整数,依次表示每多 1 人,每个人快乐程度的下降值 Di(1<=Di<=10)。
【输出格式】
应输出两行:
第1 行一个整数,是最大的快乐程度之和;
第2 行一个整数,是最大的快乐程度之和所对应的汽艇上的人数(若有多种方案,则输出人数最多的)。
【输入样例】
6
10 10 10 10 10 9
2 2 2 2 2 3
【输出样例】
18
3
【样例说明】
前 3 个人去坐汽艇可使快乐程度之和达到最大,每个人的快乐程度均为 10-2*2=6,总和是
18。
【数据范围】
对于 30%的数据,n<=20;
对于 100%的数据,n<=1000。
正解:贪心
解题报告:
标准水题,枚举有多少个人,然后每次sort,取最优的情况即可。
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 1011; int n,ans,cnt,jilu; struct node{ int val; int fall; }a[MAXN]; struct now{ int val; }jump[MAXN]; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool cmp(node q,node qq){ return q.val>qq.val; } inline bool ccmp(now q,now qq){ return q.val>qq.val; } inline void solve(){ n=getint(); for(int i=1;i<=n;i++) a[i].val=getint(); for(int i=1;i<=n;i++) a[i].fall=getint(); sort(a+1,a+n+1,cmp); ans=a[1].val; jilu=1; for(int i=2;i<=n;i++) { for(int j=1;j<=n;j++) jump[j].val=a[j].val-(i-1)*a[j].fall; sort(jump+1,jump+n+1,ccmp); cnt=0; for(int j=1;j<=i;j++) cnt+=jump[j].val; if(cnt>=ans) { ans=cnt; jilu=i; } } printf("%d\n%d",ans,jilu); } int main() { solve(); return 0; }
[b]2、上网(net.cpp/c/pas) [/b]
【问题描述】
假设有 n 个人要上网,却只有 1 台电脑可以上网。上网的时间是从 1 szw 至 T szw ,szw是一个自创的时间单位,至于 szw怎么换算成 s,min 或 h,没有人清楚。依次给出每个人在某个时间段内上网的快乐程度 C(必须这个人在整个时间段内都在上网,才能获得快乐程度C,否则,快乐程度是 0),请你得到使总的快乐程度达到最大的方案。
【输入格式】
第1 行2 个整数 n和 T,含义如题目所述;
接下来有 n 个这样的结构(每两个相邻的结构之间有一空行,且第 1 个结构和第一行间有
一空行):
第1 行一个整数 Mi,表示第 i 个人的时间段的个数;
接下来有 Mi 行,每行3个整数 Xj,Yj,C,表示第 i个人在[Xj,Yj]内上网的快乐程度为 C,
因此有 Xj-Yj-1=1,X1=1,Ymi=T,Xj<=Yj。
【输出格式】
仅输出一行,为总的最大的快乐程度。
【输入样例】
3 10
3
1 3 6
4 7 9
8 10 3
3
1 3 5
4 7 10
8 10 1
4
1 3 2
4 8 2
9 9 6
10 10 3
【输出样例】
25
【样例说明】
在[1,3]内,安排 1 上网,快乐程度为 6;
在[4,7]内,安排 2 上网,快乐程度为 10; 在[8,8]内,不安排;
在[9,9]内,安排 3 上网,快乐程度为 6;
在[10,10]内,安排 3 上网,快乐程度为 3;
这是使总的快乐程度达到最大的方案,对应的值是 25。
【数据范围】
对于 30%的数据,n<=4,所有的 Mi<=5,T<=20;
对于 60%的数据,n<=100,所有的 Mi<=100,T<=2000;
对于 100%的数据,n<=500,所有的 Mi<=500,T<=500000,所有的 0<C<=10^9,并保证最终解 Max<=10^9。
正解:DP
解题报告:
这道题我开始居然想了很久,我真是太菜了。。。
果断DP,每个人的各段区间没有任何区别,直接丢一起按照左端点排序。题目可转化为给定若干带权区间,取出不重叠的区间使权值最大。
貌似大家都是在做区间数的做法。。。我是直接讨论时间,for时间,然后记录一下处理到哪段区间,并且当前的最左端点,一维DP
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 511; const int MAXT = 500011; int n,tim; int m[MAXN]; int cnt; int f[MAXT];//f[i]表示i时刻(含)之前的最大值 struct seq{ int l,r,val; }a[MAXN*MAXN],jump[MAXN*MAXN]; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool cmp(seq q,seq qq){ if(q.l==qq.l) return q.r<qq.r; return q.l<qq.l; } int main() { n=getint(); tim=getint(); for(int i=1;i<=n;i++) { m[i]=getint(); for(int j=1;j<=m[i];j++) { a[++cnt].l=getint(); a[cnt].r=getint(); a[cnt].val=getint(); } } sort(a+1,a+cnt+1,cmp); int ji=1,nowl=a[1].l; //f[a[1].r]=a[1].val; for(int i=1;i<=tim;i++) { f[i]=max(f[i-1],f[i]); if(i<nowl) continue; while(a[ji].l==nowl && ji<=cnt) f[a[ji].r]=max(f[a[ji].r],f[i-1]+a[ji].val),ji++; nowl=a[ji].l; } printf("%d",f[tim]); return 0; }
[b]3、集合(gather)[/b]
【问题描述】
小明总喜欢做一些与众不同的事情,最近他迷上了集合运算。他觉得光是简单的预算不过瘾,所以他把2个集合运算集合起来。由于小明很喜欢区间运算。于是他定义了一个这样的值。
你N个各不相同的区间,请你从中找出若干个区间使其权值最大。
W=|A1∪A2∪……∪AK|*|A1∩A2∩……AK|
其中{A1,A2……AK}(K>1,Ai<>Aj{i<>j})
如果这些区间没有交集则权值为0,给你N个各不相同的区间,请你从中找出若干个区间使其权值最大,并告诉小明。
【输入文件】
第一行N
接下来N行 l r(1<=l<r<=10^6)
【输出文件】
最大权值
【输入样例】
4
1 6
4 8
2 7
3 5
【输出样例】
24
【数据约定】
10% N<=10
30% N<=2*10^4
50% N<=10^5
100% 1<N<=10^6
正解:决策单调性
解题报告:
考场上明明想出来了,一定是两个的时候最优,但是自己不相信自己,而且感觉n^2的暴力也会TLE就没打,打了一个大暴力,水到20分。
等我打完大暴力,心血来潮make数据发现永远是2个的时候最优。。。追悔莫及。。。
显然直接两两枚举会TLE,就要考虑优化。
题解说 用决策单调性,有一些奇奇怪怪的性质。传送门:http://www.cnblogs.com/chenyushuo/p/5261657.html
这道题居然是BZOJ原题,出题人真懒。
先贴一发大暴力:
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 1000011; int n; bool pd[MAXN]; int ans; struct seq{ int l,r; }a[MAXN],dui[MAXN]; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool cmp(seq q,seq qq){ if(q.l==qq.l) return q.r<qq.r; return q.l<qq.l; } inline void check(int cnt){ if(cnt==0 || cnt==1) return ; int total=0; for(int i=1;i<=n;i++) if(pd[i]) dui[++total]=a[i]; sort(dui+1,dui+total+1,cmp); int head=dui[1].l,tail=dui[1].r; int maxl=0; for(int i=1;i<=total;i++) head=max(head,dui[i].l),tail=min(tail,dui[i].r); if(head>=tail) return; maxl=tail-head; int nowl=dui[1].l,nowr=dui[1].r; int ji=0; ji=nowr-nowl; for(int i=2;i<=total;i++) { if(dui[i].l==nowl) ji+=dui[i].r-nowr,nowr=dui[i].r; else{ nowl=dui[i].l; if(nowl>nowr) { ji+=dui[i].r-dui[i].l; nowr=dui[i].r; } else{ if(dui[i].r>nowr) { ji+=dui[i].r-nowr; nowr=dui[i].r; } } } } maxl*=ji; if(maxl>ans) { ans=maxl; /*for(int i=1;i<=n;i++) if(pd[i]) printf("%d ",i); printf("\n%d \n",ans);*/ } } inline void dfs(int now,int cnt){ if(now==n+1) { check(cnt);return ; } pd[now]=1; dfs(now+1,cnt+1); pd[now]=0; dfs(now+1,cnt); } inline void solve(){ n=getint(); for(int i=1;i<=n;i++) a[i].l=getint(),a[i].r=getint(); dfs(1,0); printf("%d",ans); } int main() { solve(); return 0; }
正解:单调队列+单调栈
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 1000011; int n,cnt; LL ans; struct seq{ int l,r; }a[MAXN]; inline LL calc(const seq &j,const seq &i){return 1LL*(i.r-j.l)*(j.r-i.l);} inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool cmp(seq q,seq qq){ if(q.l==qq.l) return q.r>qq.r; return q.l<qq.l; } inline LL max(LL pp,LL ppp){ if(pp<ppp) return ppp; return pp; } struct stac{ int pos,top; struct data{ int l,r,id; }lin,sta[MAXN]; inline void init(){ sta[top=1]=(data){2,n,1}; pos=1; } bool comp(int xx,int x,int y){return calc(a[x],a[xx])<calc(a[y],a[xx]);} inline int get(int id){ int l=lin.l,r=lin.r,bian=lin.id; int mid; while(l<r) { mid=(l+r)/2+1; if(comp(mid,bian,id)) l=mid; else r=mid-1; } return l; } inline void push(int id){ while(top && !comp(sta[top].l,sta[top].id,id)) top--; lin=sta[top--]; int m=get(id); if(lin.l<=m) sta[++top]=(data){lin.l,m,lin.id}; if(m<n) sta[++top]=(data){m+1,n,id}; } inline LL query(int x){ while(x>sta[pos].r) pos++; return calc(a[sta[pos].id],a[x]); } }stack; struct queue{//单调队列,维护一个左端点、右端点坐标都单调递增,长度单调递减的区间队列 int head,tail; struct data{ int r,len; }seq[MAXN],lin; inline void push(int id){ lin=(data){a[id].r,a[id].r-a[id].l}; while(head<=tail && seq[tail].len<=lin.len) tail--; seq[++tail]=lin; } inline LL query(int id){ int r=a[id].r; while(head<=tail && seq[head].r<r) head++; if(head<=tail) return seq[head].len; else return -1; } }que; inline void solve(){ n=getint(); for(int i=1;i<=n;i++) a[i].l=getint(),a[i].r=getint(); sort(a+1,a+n+1,cmp); int last=0; que.head=1; for(int i=1;i<=n;i++) { if(a[i].r>last) last=a[i].r,a[++cnt]=a[i],que.push(i);//得到去掉互相包含之后的新区间集,并加入单调队列,更新当前最右的端点值 else ans=max( que.query(i)*(a[i].r-a[i].l) , ans );//计算互相包含的情况 } stack.init(); for(int i=2;i<=cnt;i++) { ans=max(ans,stack.query(i)),stack.push(i); } printf(OT,ans); } int main() { solve(); return 0; }
[b]4、新斯诺克(snooker.cpp/c/pas)[/b]
【问题描述】
斯诺克又称英式台球,是一种流行的台球运动。在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分别为 1 个白球,15 个红球和 6 个彩球(黄、绿、棕、蓝、粉红、黑)共22个球。击球顺序为一个红球、一个彩球直到红球全部落袋,然后以黄、绿、棕、蓝、粉红、黑的顺序逐个击球,最后以得分高者为胜。斯诺克的魅力还在于可以打防守球, 可以制造一些障碍球使对方无法击打目标球而被扣分。正是因为这样,斯诺克是一项充满神奇的运动。 现在考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为M,台面上有 N 个红球排成一排,每一个红球都有一个标号,`他们的标号代表了他们的分数。 现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K 到红球”。我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球。并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处。每次击打时候,要想“K到红球”,至少要击打一个红球,如果想一次击打多个红球,那么击打的红球必须是依次连续排列的。 如果一次 “K 到红球”所有红球的标号之和的平均数大于母球的标号M,就获得了一个 “连击”。 现在请你计算总共能有多少种“连击”方案。
注意:如果当前有标号为 1、2、3的三种红球,母球标号为 0, 有如下 6 种获得“连击”方案: (1) 、 (2) 、 (3) 、 (1,2) 、 (2,3) 、 (1,2,3)
【输入文件】
输入文件共有两行,第一行是 N,M (N<=100000,M<=10000),
N 表示台面上一共有 N 个红球,M 表示母球的标号。
第二行是 N 个正整数,依次表示台面上 N 个红球的标号,所有标号均不超过10000。
【输出文件】
输出文件只有一个数,为“连击”的方案总数。
【输入样例】
4 3
3 7 2 4
【输出样例】
7
正解:归并排序,逆序对
解题报告:
刚看到这道题就想到POJ上刷的那道求序列的最大平均值的神题,那个是用斜率优化、凸包优化的DP,结果发现跟这道题并没有关系,被小胖犇狠狠嘲讽了一波。
静下心来推导了一波。发现一个神奇的性质:一个区间[i,j]满足条件当且仅当(前缀和)(sum[j]-sum[i-1])/(j-i) > m,移项:(sum[j]-sum[i-1])>(j-i)*m。。。高兴地发现这就是一个逆序对。。。
直接归并排序,求前缀和的逆序对。
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 100011; int n,m; int sum[MAXN],a[MAXN],jump[MAXN]; int g[MAXN]; LL ans; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline void merge(int l,int mid,int r){ int i=l,j=mid+1; int cnt=l; while(i<=mid && j<=r) { if(jump[i]<=jump[j]) g[cnt++]=jump[i++]; else{ g[cnt++]=jump[j++]; //ans+=mid-i+1; ans+=(LL)mid; ans-=(LL)i; ans++; } } while(i<=mid) g[cnt++]=jump[i++]; while(j<=r) g[cnt++]=jump[j++]; //for(;i<=mid;i++) g[cnt++]=a[i]; //for(;j<=r;j++) g[cnt++]=a[i]; for(i=l;i<=r;i++) jump[i]=g[i]; } inline void gui(int l,int r){ if(l==r) return ; int mid=(l+r)/2; gui(l,mid); gui(mid+1,r); merge(l,mid,r); } inline void solve(){ n=getint();m=getint(); for(int i=1;i<=n;i++) { a[i]=getint(); sum[i]=sum[i-1]+a[i]; jump[i]=sum[i]-m*i; } for(int i=1;i<=n;i++) jump[i]=-jump[i];//正序对变成逆序对 gui(0,n); printf(OT,ans); } int main() { solve(); return 0; }
相关文章推荐
- leetcode-java-26. Remove Duplicates from Sorted Array
- 独上高楼, 望尽天涯路 . (路在前方)
- 微信 redirect_uri参数错误
- 微信 redirect_uri参数错误
- 给Java说句公道话-王垠
- 编解码学习笔记(七):微软Windows Media系列
- [Android] 使用 GridView 实现九宫格视图
- Java笔记(一)类与对象的基本概念
- 竖式问题
- DOS 和 Linux 常用命令的对比
- jquery输入数字随机抽奖特效的简单实现代码
- 嵌入式Linux裸机开发(十二)——iNand简介
- OPenGL 裁剪窗口
- 编解码学习笔记(五):Mpeg系列——AAC音频
- 算法#06--基本数据类型和包装
- [linux]软连接和硬连接
- html5中的Viewport标签 — 视区概念
- Subsets II
- leetcode-java-20. Valid Parentheses
- UVA816(用BFS求最短路)(wf)