CodeForces - 283E Cow Tennis Tournament

Discription

Farmer John is hosting a tennis tournament with his n cows. Each cow has a skill level si, and no two cows having the same skill level. Every cow plays every other cow exactly once in the tournament, and each cow beats every cow with skill level lower than its own.

However, Farmer John thinks the tournament will be demoralizing for the weakest cows who lose most or all of their matches, so he wants to flip some of the results. In particular, at k different instances, he will take two integers ai,?bi (ai?<?bi) and flip all the results between cows with skill level between ai and bi inclusive. That is, for any pair x,?y  he will change the result of the match on the final scoreboard (so if x won the match, the scoreboard will now display that ywon the match, and vice versa). It is possible that Farmer John will change the result of a match multiple times. It is not guaranteed that ai and bi are equal to some cow‘s skill level.

Farmer John wants to determine how balanced he made the tournament results look. In particular, he wants to count the number of triples of cows (p,?q,?r) for which the final leaderboard shows that cow p beats cow q, cow q beats cow r, and cow r beats cow p. Help him determine this number.

Note that two triples are considered different if they do not contain the same set of cows (i.e. if there is a cow in one triple that is not in the other).

Input

On the first line are two space-separated integers, n and k (3?≤?n?≤?105; 0?≤?k?≤?105). On the next line are n space-separated distinct integers, s1,?s2,?...,?sn (1?≤?si?≤?109), denoting the skill levels of the cows. On the next k lines are two space separated integers, ai and bi (1?≤?ai?<?bi?≤?109) representing the changes Farmer John made to the scoreboard in the order he makes it.

Output

A single integer, containing the number of triples of cows (p,?q,?r) for which the final leaderboard shows that cow p beats cow q, cow q beats cow r, and cow r beats cow p.

Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

Examples

Input

3 21 2 31 22 3

Output

1

Input

5 35 9 4 1 71 72 83 9

Output

3

Note

In the first sample, cow 3 > cow 1, cow 3 > cow 2, and cow 2 > cow 1. However, the results between cows 1 and 2 and cows 2 and 3 are flipped, so now FJ‘s results show that cow 1 > cow 2, cow 2 > cow 3, and cow 3 > cow 1, so cows 1, 2, and 3 form a balanced triple.

jzh大佬给学弟学妹们讲课的课件里,唯一一个不是弱智题的就是这个了2333,然鹅一找原题,mdzz数据范围后面加了俩0,有毒。。。

如果n<=1000的话,我们可以很容易的用差分去维护区间覆盖的问题,然后暴力计算每两个牛之间的比赛结果就好了。。。

所以n<=1e5怎么做呢??

我们只要先求出每个人最后赢的场数,就可以直接算出不合法的三元组数量,再用C(n,3)减去这个就是答案了。

那么如何快速计算每个人赢的场数呢?

考虑扫描线,把修改存在vector里,先倒着扫一遍,查询s[j] < s[i] 且 i赢j的个数;再倒着扫一遍,。。。。把修改看成区间异或,查询看成区间1的个数,然后这就是基本线段树操作了23333

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define pb push_back
#define lc (o<<1)
#define mid (l+r>>1)
#define rc ((o<<1)|1)
const int maxn=100005;
vector<int> L[maxn],R[maxn];
int a[maxn],n,num[maxn],k,X,Y,len[maxn*4];
int win[maxn],le,ri,sum[maxn*4],tag[maxn*4],w;
ll ans=0;

inline void maintain(int o){ sum[o]=sum[lc]+sum[rc];}

inline void work(int o){ tag[o]^=1,sum[o]=len[o]-sum[o];}

inline void pushdown(int o){
	if(tag[o]){
		tag[o]=0;
		work(lc),work(rc);
	}
}

void build(int o,int l,int r){
	len[o]=r-l+1;
	if(l==r){ sum[o]=1; return;}
	build(lc,l,mid);
	build(rc,mid+1,r);
	maintain(o);
}

void update(int o,int l,int r){
	if(l>=le&&r<=ri){ work(o); return;}
	pushdown(o);
	if(le<=mid) update(lc,l,mid);
	if(ri>mid) update(rc,mid+1,r);
	maintain(o);
}

void query(int o,int l,int r){
	if(l>=le&&r<=ri){ w+=sum[o]; return;}
	pushdown(o);
	if(le<=mid) query(lc,l,mid);
	if(ri>mid) query(rc,mid+1,r);
}

inline void solve(){
	build(1,1,n);

	for(int i=n;i;i--){
		ri=i;

		for(int j=L[i].size()-1;j>=0;j--) le=L[i][j],update(1,1,n);

		w=0,le=1,ri=i-1;
		if(le<=ri) query(1,1,n);
		win[i]+=w;

//		cout<<i<<‘ ‘<<w<<endl;
	}

	memset(sum,0,sizeof(sum));
	memset(tag,0,sizeof(tag));

	for(int i=1;i<=n;i++){
		le=i;
		for(int j=R[i].size()-1;j>=0;j--) ri=R[i][j],update(1,1,n);

		w=0,le=i+1,ri=n;
		if(le<=ri) query(1,1,n);
		win[i]+=w;

//		cout<<i<<‘ ‘<<win[i]<<endl;
	}

	for(int i=1;i<=n;i++) ans-=win[i]*(ll)(win[i]-1)>>1;
}

int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",a+i),num[i]=a[i];

	sort(num+1,num+n+1);
//	unique(num+1,num+n+1);
	for(int i=1;i<=n;i++) a[i]=lower_bound(num+1,num+n+1,a[i])-num;

	while(k--){
		scanf("%d%d",&X,&Y);
		X=lower_bound(num+1,num+n+1,X)-num;
		Y=upper_bound(num+1,num+n+1,Y)-num-1;

		if(!X||!Y) continue;

		L[Y].pb(X),R[X].pb(Y);
	}

	ans=n*(ll)(n-1)*(ll)(n-2)/6ll,solve();

	cout<<ans<<endl;

	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/9096479.html

时间: 2024-08-29 07:52:26

CodeForces - 283E Cow Tennis Tournament的相关文章

Codeforces 283E Cow Tennis Tournament 线段树 (看题解)

Cow Tennis Tournament 感觉这题的难点在于想到求违反条件的三元组.. 为什么在自己想的时候没有想到求反面呢!!!! 违反的三元组肯定存在一个人能打败其他两个人, 扫描的过程中用线段树维护一下就好了. 反思: 计数问题: 正难则反 正难则反 正难则反 !!!! #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi

283E&amp;EZOJ #89 Cow Tennis Tournament

传送门 分析 我们考虑用所有的情况减去不合法的情况 不难想出所有情况为$C_n^3$ 于是我们考虑不合法的情况 我们知道对于一个不合法的三元组$(a,b,c)$一定是修改后$a<b,b>c$ 于是我们可以离散化后用线段树维护每个点被覆盖了几次 所以每次对于一个点$i$,比它大的点的个数即为在它前面修改次数为偶数的数量加在它后面修改次数为奇数的数量 而产生的不合法情况即为$C_{sum_i}^2$ 我们再统计前后两种情况的时候将修改排序然后分别从后往前和从前往后各跑一次即可 每次只要区间不再覆盖

CF 628A --- Tennis Tournament --- 水题

CF 628A 题目大意:给定n,b,p,其中n为进行比赛的人数,b为每场进行比赛的每一位运动员需要的水的数量, p为整个赛程提供给每位运动员的毛巾数量, 每次在剩余的n人数中,挑选2^k=m(m <=n)个人进行比赛,剩余的n-m个人直接晋级, 直至只剩一人为止,问总共需要的水的数量和毛巾的数量 解题思路:毛巾数很简单: n*p即可 水的数量:1,2,4,8,16,32,64,128,256,512,提前打成一个表, 根据当前剩余的人数n在表中二分查找最大的小于等于n的数,结果即为本次进行比赛

Codeforces 735C:Tennis Championship(数学+贪心)

http://codeforces.com/problemset/problem/735/C 题意:有n个人打锦标赛,淘汰赛制度,即一个人和另一个人打,输的一方出局.问这n个人里面冠军最多能赢多少场,其中一个人和另一个人能打比赛当且仅当这两个人赢的局数相差不超过1. 思路:比赛的时候不会做..直接log2(n)交,果断错了.看题解:因为限制条件两个人能比赛当且仅当他们赢得局数相差不超过1,设F[x]为冠军赢x盘的时候需要的总人数,那么有这样的递推式:F[x] = F[x-1] + F[x-2].

Codeforces 283B Cow Program

题意:给你a[2] - a[n], 一个初始x = 1,初始y = 0  ,执行下面步骤 1) x +=a[x] ,y += a[x] 2) x -= a[x] ,y += a[x] 3)重复1-2步骤.只要中间x <=0 || x > n  就跳出.输出y的值 问你a[1] 从 [1,n-1]分别的值为多少. 解题思路:dfs 求 dp[i][0/1]  求以加法进入 i 和以减法进入 i 能得到的值. 解题代码: 1 // File Name: 283b.cpp 2 // Author:

Codeforces 1209D. Cow and Snacks

传送门 考虑构建图论模型,每个客人看成边,菜看成点,那么每个客人连接他喜欢的两个菜 对于某个客人,如果他要开心,它连接的两点至少要有一个还未被选择 考虑一个显然的贪心,我们要尽量让每个客人只吃到一种菜 考虑构建一个生成树,每次从树上一个节点往外延伸,连向一个新的点,那之间的边就是新的一个客人 并且这样构建以后,除了第一个客人吃到了两种菜以外,其他客人都只吃到一种菜,显然是最优的 发现代码实现的时候生成树连边的顺序是没影响的,所以直接构建生成树森林,那么森林中的边数就是最多可以开心的客人 答案即为

Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) C - Table Tennis Game 2

地址:http://codeforces.com/contest/765/problem/C 题目: C. Table Tennis Game 2 time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Misha and Vanya have played several table tennis sets. Each set co

codeforces 735C Tennis Championship(贪心+递推)

Tennis Championship 题目链接:http://codeforces.com/problemset/problem/735/C --每天在线,欢迎留言谈论. 题目大意: 给你一个 n (2≤n≤10^18),代表一共有n位参加比赛的选手. 游戏规则: ①每次比赛,输的选手将离开赛场 ②相互比赛的选手 他们的获胜的次数相差不能超过1(获胜4次的选手只能跟3或5次的选手比赛) 问题:最终赢得比赛的选手,胜场最多能为多少. 思路: 贪心:①选一名选手让他一直获胜且优先让他参加比赛 ②当

CodeForces - 356A Knight Tournament

http://codeforces.com/problemset/problem/356/A 首先理解题意 每次给出l 和r  在l - r之间还有资格的选手中得出一个胜者 暴力思路: 首先维护还有资格的选手的集合 用一个数组 表示 这个选手被谁击败 每次遍历 l - r 然后把不是胜者 且 还在集合中的选手踢出 并更新这个选手的数组值 最终 输出这个数组即可 这样会TLE 1. 如果用数组维护这个集合的话 每次遍历都是这样就是O(n^2) -->> 所以用set维护这个集合 2.使用set后