BZOJ4881: [Lydsy2017年5月月赛]线段游戏
来源:互联网 发布:叶陌折 知乎 编辑:程序博客网 时间:2024/06/06 18:10
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4881
Description
quailty和tangjz正在玩一个关于线段的游戏。在平面上有n条线段,编号依次为1到n。其中第i条线段的两端点坐
标分别为(0,i)和(1,p_i),其中p_1,p_2,...,p_n构成了1到n的一个排列。quailty先手,他可以选择一些互不相交
的线段,将它们拿走,当然他也可以一条线段也不选。然后tangjz必须拿走所有剩下的线段,若有两条线段相交,
那么他就输了,否则他就赢了。注意若quailty拿走了全部线段,那么tangjz也会胜利。quailty深深喜欢着tangjz
,所以他不希望tangjz输掉游戏,请计算他有多少种选择线段的方式,使得tangjz可以赢得游戏。
Input
第一行包含一个正整数n(1<=n<=100000),表示线段的个数。
第二行包含n个正整数p_1,p_2,...,p_n(1<=p_i<=n),含义如题面所述。
Output
输出一行一个整数,即tangjz胜利的方案数,因为答案很大,请对998244353取模输出。
Sample Input
5
1 2 4 5 3
1 2 4 5 3
Sample Output
8
若线段 i 和j 相交,那么在它们之间连一条边。若这个图不是二分图,那么无解,否则令cnt 为连通块个数,那么 ans = 2cnt。
在二分图染色的过程中,每个点只需要被访问一次。对于当前所在的点 x,它可以一步走到 [1; x) 里p[i] > p[x] 的所有i,以及 (x; n] 里p[j] < p[x] 的所有j。用线段树维护所有没走过
的点,记录每个区间 p 最小与最大的两个位置。每次贪心取出最大/小的,看看是否满足条件,若满足则删除该点,然后递归染色,否则终止。
时间复杂度 O(n log n)。
//二分图染色,线段树加速#include<cstdio>#include<cstdlib>const int N=100010,M=262150;int n,i,a[N],ma[M],mi[M],pos[N],tmp,col[N],f[3],ret,ans;inline int mergema(int x,int y){ if(!x||!y)return x+y; return a[x]>a[y]?x:y;}inline int mergemi(int x,int y){ if(!x||!y)return x+y; return a[x]<a[y]?x:y;}inline void up(int x){ ma[x]=mergema(ma[x<<1],ma[x<<1|1]); mi[x]=mergemi(mi[x<<1],mi[x<<1|1]);}void build(int x,int a,int b){ if(a==b){ ma[x]=mi[x]=a; pos[a]=x; return; } int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b); up(x);}inline void del(int x){ x=pos[x]; ma[x]=mi[x]=0; for(x>>=1;x;x>>=1)up(x);}void askma(int x,int a,int b,int c,int d){ if(c<=a&&b<=d){ tmp=mergema(tmp,ma[x]); return; } int mid=(a+b)>>1; if(c<=mid)askma(x<<1,a,mid,c,d); if(d>mid)askma(x<<1|1,mid+1,b,c,d);}void askmi(int x,int a,int b,int c,int d){ if(c<=a&&b<=d){ tmp=mergemi(tmp,mi[x]); return; } int mid=(a+b)>>1; if(c<=mid)askmi(x<<1,a,mid,c,d); if(d>mid)askmi(x<<1|1,mid+1,b,c,d);}void dfs(int x,int y){ del(x); col[x]=y; y=3-y; while(1){ tmp=0; askmi(1,1,n,x,n); if(tmp&&a[tmp]<a[x])dfs(tmp,y);else break; } while(1){ tmp=0; askma(1,1,n,1,x); if(tmp&&a[tmp]>a[x])dfs(tmp,y);else break; }}int main(){ scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); build(1,1,n); for(i=1;i<=n;i++)if(!col[i])dfs(i,1),ret++; for(i=1;i<=n;i++){ if(a[i]<f[col[i]])return puts("0"),0; f[col[i]]=a[i]; } ans=1; while(ret--)ans=ans*2%998244353; printf("%d",ans); return 0;}
阅读全文
1 0
- bzoj4881: [Lydsy2017年5月月赛]线段游戏
- BZOJ4881 [Lydsy2017年5月月赛]线段游戏
- BZOJ4881: [Lydsy2017年5月月赛]线段游戏
- bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树
- 4881: [Lydsy2017年5月月赛]线段游戏
- bzoj 4881: [Lydsy2017年5月月赛]线段游戏 树状数组+set
- BZOJ4886 [Lydsy2017年5月月赛]叠塔游戏
- BZOJ4886: [Lydsy2017年5月月赛]叠塔游戏
- 4886: [Lydsy2017年5月月赛]叠塔游戏
- bzoj4885: [Lydsy2017年5月月赛]长方体
- BZOJ4885: [Lydsy2017年5月月赛]长方体
- bzoj5049 [Lydsy2017年5月月赛]导航系统
- BZOJ 4881 [Lydsy2017年5月月赛] 二分图染色+线段树
- bzoj 4886: [Lydsy2017年5月月赛]叠塔游戏 并查集
- [bzoj4881]线段游戏
- bzoj 4880: [Lydsy2017年5月月赛]排名的战争
- bzoj4878: [Lydsy2017年5月月赛]挑战NP-Hard
- bzoj4879: [Lydsy2017年5月月赛]失控的数位板
- bootstrap table 简介01
- 图片切换(一)(div+css+js)
- Docker命令行与守护进程如何交互?
- 特征选择之遗传算法
- kotlin学习笔记(二)
- BZOJ4881: [Lydsy2017年5月月赛]线段游戏
- 《算法导论》第13章 红黑树 个人笔记
- DispatherServlet配置url-pattern中的一个小细节
- 电视机的历史:录像带机》黑白电视》彩色电视+光盘机》计算机||曲面显示器,还是3d操作系统好
- JavaScript原型和原型链
- LeetCode 7. Reverse Integer
- 网页设计与制作(HTML+CSS)(三)
- 数据结构七线性表
- BZOJ4882: [Lydsy2017年5月月赛]卡常生成树