bzoj 4879 失控的数位板 4881 线段游戏 贪心,瞎搞
[Lydsy1705月赛]失控的数位板
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 148 Solved: 33
[Submit][Status][Discuss]
Description
绘画家小Q正在他的数位板上作画。当他在作画的时候,他的设备突然故障了!此时他的笔变成了擦除模式。在小Q
的脑海中,有一副漂亮的图案,他希望最后能将它呈现在板子上。他按照自己的创作风格,一步一步地绘画。他每
一步只可能是4种指令上(up)下(down)左(left)右(right)中的一种,同时指定一个距离d,每秒往那个方向移动一
步。在创作的一开始,他的笔位于数位板的左下角,且任意时刻他的笔都不会离开数位板。考虑6*8的数位板以及
如下图所示的指令集,如果笔在第17秒末故障了,数位板最终会变成第二幅图的样子。
小Q想知道最早和最晚的时刻t,满足如果数位板在第t秒末故障了,最终显示出来的图案与他预想的一致。注意数
位板可以在第0秒末故障,此时小Q的笔还没有触碰到数位板。
Input
第一行包含三个正整数h,w,n(1<=h,w,n<=10^6,1<=w*h<=10^6),分别表示数位板的高度与宽度以及指令的条数。
接下来h行,每行w个字符
每个字符要么是“#”,要么是“.”。表示小Q预想的效果,其中“#”表示有颜色,“.”表示空白。
接下来n行
每行一个字符串s和一个正整数d(1<=d<=10^6),分别表示方向和距离,输入数据保证操作不会使笔离开数位板。
Output
输出一行两个整数x与y,其中x表示最小的合法的t,y表示最大的合法的t
注意y不能超过最后一条指令执行完毕时的时间。若无解则输出“-1 -1”。
Sample Input
6 8 5
........
........
###.####
#......#
#..#####
#.......
up 3
right 7
down 2
left 4
up 3
........
........
###.####
#......#
#..#####
#.......
up 3
right 7
down 2
left 4
up 3
Sample Output
17 17
HINT
[Lydsy1705月赛]线段游戏
Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 322 Solved: 184
[Submit][Status][Discuss]
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
HINT
Source
题解:对于数控板,对于一个数如果有颜色那么时间一定在其后,
如果本应该有颜色但是现在没颜色了,那么时间一定在其之前。
对于线段的话,
题意可理解为给定一个序列,求将这个序列分成两个上升序列的方案数
先判断是否输出0,方法是用树状数组求最长下降序列,若长度>2,说明无解
然后从左往右扫,将这些数一个一个加到set里,在加入之前,先将set中比当前数大的数全都删掉,
然后将这些数中最大的数加到set中去,最后若set中还剩m个数,答案就是2^m
为什么这样理解,对于小的数当然是随便选,想后面的,加入一个数,如果比当前最大的数大,那么直接加入
否则,必然和前面构成矛盾,将这些数删除,留下最大是因为之后如果不影响的话,必须必当前最大值更大才行。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int M=1e6+5; 5 int h,w,n,op[M],d[M],nex[4][2]={-1,0,0,1,1,0,0,-1},curx,cury; 6 ll t,L,R; 7 set<int> sx[M],sy[M]; 8 char s[M]; 9 int getop(char *s){ 10 if(s[0]=='u') return 0; 11 if(s[0]=='r') return 1; 12 if(s[0]=='d') return 2; 13 if(s[0]=='l') return 3; 14 } 15 char ask(int x,int y,bool flag){ 16 if(flag) swap(x,y); 17 return s[x*w+y]; 18 } 19 void solve(set<int> &s,int st,int ed,ll tl,int wh,bool flag){ 20 int l=st,r=ed; 21 if(l>r) swap(l,r); 22 for(set<int>::iterator it=s.lower_bound(l);it!=s.end()&&*it<=r;){ 23 if(flag) sx[*it].erase(sx[*it].find(wh)); 24 else sy[*it].erase(sy[*it].find(wh)); 25 if(ask(wh,*it,flag)=='#') L=max(L,tl-abs(*it-st)); 26 else R=min(R,tl-abs(*it-st)-1); 27 s.erase(it++); 28 } 29 } 30 int main(){ 31 scanf("%d%d%d",&h,&w,&n); 32 for(int i=0;i<h;i++) 33 scanf("%s",s+i*w); 34 for(int i=1;i<=n;i++){ 35 char tmp[10]; 36 scanf("%s%d",tmp,&d[i]); 37 op[i]=getop(tmp); 38 } 39 for(int i=0;i<h;i++) 40 for(int j=0;j<w;j++) sx[i].insert(j); 41 for(int i=0;i<w;i++) 42 for(int j=0;j<h;j++) sy[i].insert(j); 43 curx=h-1; 44 cury=0; 45 t=1; 46 for(int i=1;i<=n;i++){ 47 t+=d[i]; 48 curx+=nex[op[i]][0]*d[i]; 49 cury+=nex[op[i]][1]*d[i]; 50 } 51 R=t; 52 for(int i=n;i;i--){ 53 int tp=(op[i]+2)%4; 54 int nx=curx+nex[tp][0]*d[i],ny=cury+nex[tp][1]*d[i]; 55 if(tp%2) solve(sx[curx],cury,ny,t,curx,0); 56 else solve(sy[cury],curx,nx,t,cury,1); 57 t-=d[i]; 58 curx=nx; 59 cury=ny; 60 } 61 for(int i=0;i<h&&L<=R;i++){ 62 for(set<int>::iterator it=sx[i].begin();it!=sx[i].end();it++){ 63 if(ask(i,*it,0)=='#'){ 64 L=R+1; 65 break; 66 } 67 } 68 } 69 if(L>R) L=R=-1; 70 printf("%lld %lld\n",L,R); 71 }
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <set> 5 using namespace std; 6 int n,ans,v[100010],tr[100010]; 7 set<int> s; 8 void updata(int x,int val) 9 { 10 for(int i=x;i<=n;i+=i&-i) tr[i]=max(val,tr[i]); 11 } 12 int query(int x) 13 { 14 int i=x,ret=0; 15 for(i=x;i;i-=i&-i) ret=max(ret,tr[i]); 16 return ret; 17 } 18 int main() 19 { 20 scanf("%d",&n); 21 int i,a,b; 22 set<int>::iterator it; 23 for(i=1;i<=n;i++) scanf("%d",&v[i]); 24 for(i=n;i>=1;i--) 25 { 26 a=query(v[i]-1)+1; 27 if(a>=3) 28 { 29 printf("0"); 30 return 0; 31 32 } 33 updata(v[i],a); 34 } 35 for(i=1;i<=n;i++) 36 { 37 b=v[i]; 38 while(!s.empty()) 39 { 40 it=s.upper_bound(b); 41 if(it==s.end()) break; 42 b=*it,s.erase(b); 43 } 44 s.insert(b); 45 } 46 b=s.size(),ans=1; 47 while(b--) ans=(ans*2)%998244353; 48 printf("%d",ans); 49 return 0; 50 }