bzoj 4879 失控的数位板 4881 线段游戏 贪心,瞎搞

[Lydsy1705月赛]失控的数位板

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 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

Sample Output

17 17

HINT

 

 [Lydsy1705月赛]线段游戏

Time Limit: 3 Sec  Memory Limit: 256 MB
Submit: 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

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 }

 

posted @ 2018-03-31 15:05  Kaiser-  阅读(313)  评论(0编辑  收藏  举报