HDU 4339 Query

算法:

比赛时没有想到好的算法,暴力是O( Q * N )肯定超时。

赛后,线段树,树状数组,HASH都能AC,想了下,的确用树状数组

时间复杂度就可以优化到O(Q * lgN * lgN)

2000msAC.。。

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 2000100
char str1[MAXN],str2[MAXN],str[10];
int  dx[MAXN];
int N, lenmax, lenmin;

int lowbit( int x )
{    
   return x&-x;   
}

void add( int x, int val, int M)
{
  while( x <= M )
  {
      dx[x] += val;
      x += lowbit(x);
  }     
     
}

int sum( int x )
{
  int num = 0;
  while( x > 0 )
  {
     num += dx[x];
     x -= lowbit( x );      
  }   
  return num;  
}

void pre( )
{
  int i = 1;
  int len1 = strlen(str1+1), len2 = strlen(str2+1);
  lenmin = len1 < len2 ? len1 : len2;
  while( i <= len1 )
  {
    if( str1[i] == str2[i] )
    {
       add(i, 1, lenmin);   
    }     
    i++;       
  }          
}

bool jugde(int start, int x)
{
  int x1 = sum(start+x-1) - sum(start-1);
  if( x1 == x )
      return true;
  return false;
}

int find( int l, int r, int start)
{
  int ans = 0;
  while( l <= r )
  {
    int mid = (l + r)/2;
    if( jugde(start,mid) )
    {
       ans = mid;
       l = mid + 1;    
        
    }
    else 
       r = mid - 1; 
           
  }
  return ans;  
}

int main( )
{
  int T, a, b, c, ans = 1;
  scanf("%d",&T);
  while( T-- )
  {
    scanf("%s%s",str1+1,str2+1);      
    scanf("%d",&N);
    memset(dx,0,sizeof(dx));
    pre( );
    printf("Case %d:\n",ans++);
    for( int i = 1; i <= N; i++)
    {
       scanf("%d",&a);
       if( a == 2 )
       {
          scanf("%d",&b);
          b++;
          printf("%d\n",find(0,lenmin,b));
       }
       else
       { 
         scanf("%d%d%s",&b,&c,str);
         c++;  
         if( str1[c] == str2[c] && str[0] != str1[c] )
         {
            add(c,-1,lenmin);
            if( b == 1 )
                str1[c] = str[0];
            else
                str2[c] = str[0];
         }
         else if( str1[c] != str2[c] )
         {
            if( b == 1 )
            {
               if( str2[c] == str[0] )
               {
                  add(c,1,lenmin);   
                  str1[c] = str[0];     
               }
               else
                 str1[c] = str[0];    
                
            }
            else if( b == 2 )
            {
               if( str1[c] == str[0] )
               {
                  add(c,1,lenmin);   
                  str2[c] = str[0];     
               }     
               else
                 str2[c] = str[0];  
                 
            }     
              
         } 
         
              
       }
         
    }     
  }
  return 0;
}

HASH,要用到差值取模,时间复杂度为O( Q * lgN),写了一两个小时,还在调试中。。代码能力弱啊。。。

明天继续搞。。

郁闷啊。。从下到上的最大长度写了N久没写出,自己感觉真的不好写,从上到下真的很好写,利用回溯,写起来真的方便,自己。。

一直被标程的从下到上困扰,真的二,忘记了还可以从上到下。thanks 旭。。

View Code
#pragma comment(linker, "/STACK:16777216")
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 1000010
#define Prime 29
#define LL long long
struct node
{
 int left, right;
 LL w1,w2;
}seg[MAXN<<4];
char str1[MAXN], str2[MAXN], str[10];
LL P[MAXN];
int num[MAXN], nmax;

void pre( )
{
   P[0] = 1;
   for( int i = 1;  i <= 1000005; i++)
       P[i] = P[i-1] * Prime;     
     
}

void build( int l, int r, int root )
{
   int mid = (l + r) / 2;
   seg[root].left = l;
   seg[root].right = r;
   if( l == r )
   {
      seg[root].w1 = str1[l];
      seg[root].w2 = str2[l];
      num[l] = root;
      return;  
   }
   build(l, mid, root * 2 );
   build(mid+1,r,root * 2 + 1);
   seg[root].w1 = seg[root << 1].w1 + seg[(root<<1)+1].w1 * P[( seg[root<<1].right - seg[root<<1].left + 1)];
   seg[root].w2 = seg[root << 1].w2 + seg[(root<<1)+1].w2 * P[( seg[root<<1].right - seg[root<<1].left + 1)];
}

void Modify( int root, int x, char c, int f)
{
  int mid = (seg[root].left + seg[root].right) / 2;
  int l = seg[root].left;
  int r = seg[root].right;
  if( l == x && r == x )
  {
       if( f == 1 )
           seg[root].w1 = c ;
       else
           seg[root].w2 = c ;
       return;
  }
  if( x > mid )
      Modify( (root << 1) + 1, x, c, f);
  else
      Modify( root << 1, x, c, f);
  if( f == 1 )
  seg[root].w1 = seg[root << 1].w1 + seg[(root<<1)+1].w1 * P[( seg[root<<1].right - seg[root<<1].left + 1)];
  else
  seg[root].w2 = seg[root << 1].w2 + seg[(root<<1)+1].w2 * P[( seg[root<<1].right - seg[root<<1].left + 1)];            
}

int find( int p)
{
  if( seg[p].w1 == seg[p].w2 )
  {
     return seg[p].right - seg[p].left + 1;  
  }
  else if( seg[p].left != seg[p].right )
  {
     int ret = find( p << 1);
     if( ret == seg[p<<1].right - seg[p<<1].left + 1 )
     {
         ret +=  find( (p << 1) + 1);    
     }
     return ret;  
  }
  else
     return 0;
}

int sum( int p, int x)
{
  if( seg[p].left == seg[p].right )
  {
     if( seg[p].w1 == seg[p].w2 )
     {
        return 1;    
     }   
     else
        return 0;   
  }    
  else
  {
     int mid = (seg[p].left + seg[p].right) / 2, ret;
     if( x <= mid )
     {
         ret = sum( p << 1, x );
         if( ret == seg[p<<1].right - x + 1 ) //左子树满的
         {
             ret += find((p << 1) + 1);
         } 
     }    
     else
     {
        ret = sum( (p << 1) + 1, x );    
     }
     return ret; 
  }  
}


int main( )
{
   int N,T, a, b, c, abc = 1;
   scanf("%d",&T);
   pre( );
   while( T-- )
   {
     scanf("%s%s",str1,str2);
     scanf("%d",&N);
     int len1 = strlen(str1);
     int len2 = strlen(str2);
     nmax = len1 < len2 ? len1 : len2;
     build(0,nmax-1,1);
     printf("Case %d:\n",abc++);
     for( int i = 1; i <= N; i++)
     {
        scanf("%d",&a);
        if( a == 2 )
        {
           scanf("%d",&b);
           if( b >= nmax )
           {
             puts("0");
             continue;    
           }
           printf("%d\n",sum(1,b));        
        }
        else
        {
           scanf("%d%d%s",&b,&c,str);
           if( c >= nmax )
           {
            // puts("0");
             continue;
           }
           Modify(1,c,str[0], b);
        }
          
     }
          
   }
   return 0;
}

posted on 2012-08-03 22:16  more think, more gains  阅读(207)  评论(0编辑  收藏  举报

导航