DLUT onsite【线段树+数学+dp专场有木有!!!】[改](D + F)(zju 3542 + zju 3544)

DLUT onsite【线段树+数学+dp专场有木有!!!】[改](D + F)(zju 3542 + zju 3544)

虽然是用了10小时来打5小时的比赛,但也弱爆了。神马都不会啊。
A zoj 3539
搜索+字符串,连暴力都不会写
B zoj 3540
竟然是矩形并!!!。。不过就算是“矩形并”,也不会写。。线段树神马的,都不会哇。。
C zoj 3541
好巧妙好经典的N^2DP,我不会啊。
D zoj 3542
纯模拟。。。善用cctype和%x
代码:
#include  < iostream >
#include 
< cstdio >
#include 
< cstring >
#include 
< string >
#include 
< cstdlib >
#include 
< cctype >
#include 
< map >
#include 
< set >
#include 
< bitset >
#include 
< vector >
#include 
< algorithm >
#include 
< cmath >
#define  PB push_back
using   namespace  std;
const   int  inf  =   ~ 0u   >>   1 ;
const   double  eps  =  1e - 8 ;
const   double  pi  =  acos( - 1.0 );
int  sgn( double  x)
{
    
return  fabs(x)  <  eps  ?   0 :x  <   - eps ?- 1 : 1 ;
}
char  str[ 5000 ];
int  main()
{
    
while (cin.getline(str, 5000 ))
    {
        
int  l  =  strlen(str);
        
int  i  =   0 ;
        
char  opt[ 20 ];
        
int  cnt  =   0 ;
        
while ( 1 )
        {
            
char  row[ 5 ];
            sprintf(row,
" %x " ,i);
            
for ( int  j  =   0 ;j  <   4   -  strlen(row);j ++ )
                putchar(
' 0 ' );
            printf(
" %s:  " ,row);
            
bool  mark  =   true ;
            
for ( int  j  =   0 ;j  <   16 ;j ++ )
            {
                opt[j] 
=  mark ? str[i]: - 1 ;
                i
++ ;
                
if (i  ==  l)
                    mark 
=   false ;
            }
            
for ( int  j  =   0 ;j  <   16 ;j ++ )
            {
                
if (opt[j]  !=   - 1 )
                    printf(
" %x " ,opt[j]);
                
else
                    printf(
"    " );
                
if (j % 2 )
                    printf(
"   " );
            }
            
for ( int  j  =   0 ;j  <   16 ;j ++ )
            {
                
if (opt[j]  ==   - 1 )
                    
break ;
                
if (islower(opt[j]))
                    opt[j] 
=  toupper(opt[j]);
                
else   if (isupper(opt[j]))
                    opt[j] 
=  tolower(opt[j]);
                printf(
" %c " ,opt[j]);
            }
            puts(
"" );
            
if ( ! mark)
                
break ;
        }
    }
}
Up
backward paragraph
E zoj 3543
N^2 dp,claire大神想了个神做法N^3,结果TLE了,哈哈~
F zoj 3544
200棵线段树,O(q * n * log(m)),ykwd大神去玩了,结果线段树部分没人敲了,不会啊。
shi哥说有O(n*m)的做法,不会啊。
shi哥的路径压缩的方法场上想到了,不会敲;到现在也不会敲。拿stl企图骗过去,果断TLE。好紧啊。
历时3天,终于AC了。链表路径压缩,orz。果断就是并查集的写法。
题解:
正着做就是裸体有lazy tag的线段树,竟然在zoj上可以过,太orz了。
刷板报什么的,有这样一个性质,后面的涂色不会被前面的覆盖,果断倒着做。
倒着做也可以某种线段树,不需要重复覆盖的,应该会比正着做要快。
(ps,既然正着做倒着做在zoj上都能过,为啥10.2的时候就只有那么点人过了F?不解)
说一下正解吧,太orz shi哥了。
我只想到了路径压缩 ,没有想到shi哥的并查集式路径压缩。(好像路径压缩就是在并查集里才常用的吧?我这个蒟蒻为毛没想到?!)

既然是不会重复覆盖,那么只要把已经覆盖过的删除了就好了,再覆盖的时候对删除的跳过去就行。这样最多删除O(m*n)次。
但是怎样快速查找呢?就是并查集的做法了,并查集路径压缩之后的复杂度在整数范围内最大为O(5)。
本题中的并查集:
删除[l,r]区间:
1.假如起始点未被删除过,那么就从这个点开始逐次删除,并统计删除的点数,返回删除的点数即可。
删除的过程中,记得将刚刚被删除的点的skip域指向本次删除区间的左端点。
2.假如起始点已经被删除过,那么就找这个点的skip域,直到找到一个可删除节点或者到本段的段尾为止(m)。
而接下来逐次删除的时候,删完的点的skip应该指向这个新的节点。
记得查找的时候,附带路径压缩,并查集的路径压缩各位大神肯定都会写吧?
删完了一个区间之后,把区间开始删除的点的skip域指向最后的点(不在本次删除范围内的可删除节点或者段末)。
牢记:路径压缩的时候是把所有儿子都指向父亲。
最后更新“最后节点“的时候,是将删除区间的起始点指向最后节点(根)。

以上说得很乱,画图解释就是:
这是naive的并查集,a exists in (l,r],a -> l,l -> (r+1)。
路径压缩的时候,l1 -> l2 -> l3 -> r => l1 -> r ,l2 -> r , l3 -> r。
关键代码在51~69行。(因为带了行号,所以复制不方便了哈。。)

数据结构神马的太神奇了。
代码如下:
  1  #include  < iostream >
  2  #include  < cstdio >
  3  #include  < cstring >
  4  #include  < string >
  5  #include  < cstdlib >
  6  #include  < cctype >
  7  #include  < map >
  8  #include  < set >
  9  #include  < bitset >
 10  #include  < vector >
 11  #include  < algorithm >
 12  #include  < cmath >
 13  #define  PB push_back
 14  #define  sqr(x) ((x) * (x))
 15  using   namespace  std;
 16  const   int  inf  =   ~ 0u   >>   1 ;
 17  const   double  eps  =  1e - 8 ;
 18  const   double  pi  =  acos( - 1.0 );
 19  int  sgn( double  x)
 20  {
 21       return  fabs(x)  <  eps  ?   0 :x  <   - eps ?- 1 : 1 ;
 22  }
 23  #define  maxn 205
 24  #define  maxm 50005
 25  int  n,m,q;
 26  inline  int  ab( int  x)
 27  {
 28       return  x  >=   0 ? x: - x;
 29  }
 30  struct  method
 31  {
 32       int  type;
 33       int  cnt;
 34       int   in [ 7 ];
 35  }mth[maxm];
 36  int  ans[ 10 ];
 37  struct  skiplist
 38  {
 39       int  skip[maxm];
 40       bool  tr[maxm];
 41       void  init( int  m)
 42      {
 43          fill(tr,tr  +  m, 1 );
 44      }
 45       int  jump( int  pos)
 46      {
 47           if (pos  >=  m)
 48               return  m;
 49           return  tr[pos] ? pos:skip[pos]  =  jump(skip[pos]);
 50      }
 51       int  erase( int  l, int  r)
 52      {
 53           int  now  =  jump(l),pos  =  now; //
 54           int  num  =   0 ;
 55           while (pos  <=  r)
 56          {
 57               if (tr[pos])
 58              {
 59                  tr[pos]  =   false ;
 60                  skip[pos]  =  now;
 61                  pos ++ ;
 62                  num ++ ;
 63              }
 64               else
 65                  pos  =  jump(pos);
 66          }
 67          skip[now]  =  pos;
 68           return  num;
 69      }
 70  }skip[maxn];
 71  void  gao( int  row, int  le, int  ri, int  co)
 72  {
 73      ans[co]  +=  skip[row].erase(le,ri);
 74  }
 75  int  main()
 76  {
 77       while (scanf( " %d %d %d " , & n, & m, & q)  ==   3 )
 78      {
 79           for ( int  i  =   0 ;i  <  n;i ++ )
 80              skip[i].init(m);
 81          memset(ans, 0 , sizeof (ans));
 82           for ( int  i  =   0 ;i  <  q;i ++ )
 83          {
 84               char  opt[ 20 ];
 85               int  a[ 10 ];
 86              scanf( " %s " ,opt);
 87               switch (opt[ 0 ])
 88              {
 89                   case   ' C ' :
 90                      mth[i].type  =   1 ;
 91                      mth[i].cnt  =   4 ;
 92                       break ;
 93                   case   ' D ' :
 94                      mth[i].type  =   2 ;
 95                      mth[i].cnt  =   4 ;
 96                       break ;
 97                   case   ' R ' :
 98                      mth[i].type  =   3 ;
 99                      mth[i].cnt  =   5 ;
100                       break ;
101                   case   ' T ' :
102                      mth[i].type  =   4 ;
103                      mth[i].cnt  =   4 ;
104                       break ;
105              }
106               for ( int  j  =   0 ;j  <  mth[i].cnt;j ++ )
107                  scanf( " %d " , & mth[i]. in [j]);
108          }
109           for ( int  i  =  q  -   1 ;i  >=   0 ;i -- )
110          {
111               int  hi,lo,le,ri,c,cnt  =  mth[i].cnt,type  =  mth[i].type;
112               int   in [ 10 ];
113               for ( int  j  =   0 ;j  <  cnt;j ++ )
114                   in [j]  =  mth[i]. in [j];
115              c  =   in [cnt - 1 ];
116               if (mth[i].type  ==   1 )
117              {
118                  hi  =  max( 0 , in [ 0 -   in [ 2 ]);
119                  lo  =  min(n  -   1 , in [ 0 +   in [ 2 ]);
120                   for ( int  j  =  hi;j  <=  lo;j ++ )
121                  {
122                       int  offset  =  floor(sqrt(sqr( in [ 2 ])  -  sqr(j  -   in [ 0 ])));
123                      le  =  max( 0 , in [ 1 -  offset);
124                      ri  =  min(m  -   1 , in [ 1 +  offset);
125                      gao(j,le,ri,c);
126                  }
127              }
128               else   if (mth[i].type  ==   2 )
129              {
130                  hi  =  max( 0 , in [ 0 -   in [ 2 ]);
131                  lo  =  min(n  -   1 , in [ 0 +   in [ 2 ]);
132                   for ( int  j  =  hi;j  <=  lo;j ++ )
133                  {
134                       int  offset  =   in [ 2 -  ab(j  -   in [ 0 ]);
135                      le  =  max( 0 , in [ 1 -  offset);
136                      ri  =  min(m  -   1 , in [ 1 +  offset);
137                      gao(j,le,ri,c);
138                  }
139              }
140               else   if (mth[i].type  ==   3 )
141              {
142                  hi  =   in [ 0 ];
143                  lo  =  min(n  -   1 , in [ 0 +   in [ 2 -   1 );
144                   for ( int  j  =  hi;j  <=  lo;j ++ )
145                  {
146                      le  =   in [ 1 ];
147                      ri  =  min(m  -   1 , in [ 1 +   in [ 3 -   1 );
148                      gao(j,le,ri,c);
149                  }
150              }
151               else
152              {
153                  hi  =   in [ 0 ];
154                  lo  =  min(n  -   1 , in [ 0 +   in [ 2 /   2 );
155                   for ( int  j  =  hi;j  <=  lo;j ++ )
156                  {
157                       int  offset  =  ( in [ 2 -  (j  -   in [ 0 ])  *   2 /   2 ;
158                      le  =  max( 0 , in [ 1 -  offset);
159                      ri  =  min(m  -   1 , in [ 1 +  offset);
160                      gao(j,le,ri,c);
161                  }
162              }
163          }
164           for ( int  i  =   1 ;i  <=   9 ;i ++ )
165              printf( " %d%c " ,ans[i],i == 9 ? ' \n ' : '   ' );
166      }
167  }
168 

G zoj 3445
状态dp+ac自动机,orz ykwd大神。
H zoj 3546
因为有凹多边形的存在,我只能想到N!的做法。这,旋转路径规划?怎么想起了昨晚的rujia几何场的最后一题,谁更难真不好说。
I zoj 3547
四次方和公式+暴力容斥,orz claire_大神
J zoj 3548
推个式子再dp,式子推出来了,dp没人做,弱爆了。
推完式子剩下的就是二分图匹配。。。这场竟然有图论,我tmd竟然没看出来。弱爆了。

弱爆了弱爆了。

你可能感兴趣的:(DLUT onsite【线段树+数学+dp专场有木有!!!】[改](D + F)(zju 3542 + zju 3544))