链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1166
 #include "iostream"
#include "iostream"
 #include "cstring"
#include "cstring"
 using namespace std;
using namespace std;
 struct segment_tree
struct segment_tree


 {
{
 int left,right,num;
    int left,right,num;
 }tree[150010];
}tree[150010];

 int a[50010];
int a[50010];
 int T,n;
int T,n;

 void Build(int left,int right,int i)
void Build(int left,int right,int i)


 {
{
 tree[i].left=left;
    tree[i].left=left;
 tree[i].right=right;
    tree[i].right=right;
 if(left==right)
    if(left==right)

 
     {
{
 tree[i].num=a[left];
        tree[i].num=a[left];
 return;
        return;
 }
    }
 int mid=(left+right)/2;
    int mid=(left+right)/2;
 Build(left,mid,2*i);
    Build(left,mid,2*i);
 Build(mid+1,right,2*i+1);
    Build(mid+1,right,2*i+1);
 tree[i].num=tree[2*i].num+tree[2*i+1].num;
    tree[i].num=tree[2*i].num+tree[2*i+1].num;
 }
}

 void Updata(int id,int num,int i)
void Updata(int id,int num,int i)


 {
{
 if(tree[i].left==tree[i].right)
    if(tree[i].left==tree[i].right)

 
     {
{
 tree[i].num+=num;
        tree[i].num+=num;
 return;
        return;
 }
    }
 else
    else

 
     {
{
 tree[i].num+=num;
        tree[i].num+=num;
 if(id<=tree[i*2].right) Updata(id,num,i*2);
        if(id<=tree[i*2].right) Updata(id,num,i*2);
 else Updata(id,num,i*2+1);
        else Updata(id,num,i*2+1);
 }
    }
 }
}

 int Query(int left,int right,int i)
int Query(int left,int right,int i)


 {
{
 if(tree[i].left==left&&tree[i].right==right) return tree[i].num;
    if(tree[i].left==left&&tree[i].right==right) return tree[i].num;
 int mid=(tree[i].left+tree[i].right)/2;
    int mid=(tree[i].left+tree[i].right)/2;
 if(right<=mid) return Query(left,right,i*2);
    if(right<=mid) return Query(left,right,i*2);
 else if(left>mid) return Query(left,right,i*2+1);
    else if(left>mid) return Query(left,right,i*2+1);
 else return Query(left,mid,i*2)+Query(mid+1,right,i*2+1);
    else return Query(left,mid,i*2)+Query(mid+1,right,i*2+1);
 }
}

 int main()
int main()


 {
{
 int i,t1,t2;
    int i,t1,t2;
 char s[10];
    char s[10];
 scanf("%d",&T);
    scanf("%d",&T);
 for(int k=1;k<=T;k++)
    for(int k=1;k<=T;k++)

 
     {
{
 scanf("%d",&n);
        scanf("%d",&n);
 for(i=1;i<=n;i++) scanf("%d",&a[i]);
        for(i=1;i<=n;i++) scanf("%d",&a[i]);
 Build(1,n,1);
         Build(1,n,1);
 printf("Case %d:\n",k);
        printf("Case %d:\n",k);
 while(1)
        while(1)

 
         {
{
 scanf("%s",s);
            scanf("%s",s);
 if(strcmp(s,"End")==0) break;
            if(strcmp(s,"End")==0) break;
 scanf("%d%d",&t1,&t2);
            scanf("%d%d",&t1,&t2);
 if(strcmp(s,"Query")==0)
            if(strcmp(s,"Query")==0)

 
             {
{
 int ans=Query(t1,t2,1);
                int ans=Query(t1,t2,1);
 printf("%d\n",ans);
                printf("%d\n",ans);
 }
            }
 if(strcmp(s,"Sub")==0) Updata(t1,-t2,1);
            if(strcmp(s,"Sub")==0) Updata(t1,-t2,1);
 if(strcmp(s,"Add")==0) Updata(t1,t2,1);
            if(strcmp(s,"Add")==0) Updata(t1,t2,1);
 }
        }
 }
    }
 return 0;
    return 0;
 }
}posted @ 
2010-11-14 12:45 wuxu 阅读(311) | 
评论 (0) | 
编辑 收藏题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1042
这道题是大数和普通数的乘法,步骤如下:
1、判断乘后大数的位数,此题约为40000;
2、选择由那种类型数组存储,一般由int存储,一个数能存5位(10000*100000<2^31);
3、确定数组长度,此题约为40000/5=8000;
4、计算数组中每个数与普通数的乘积并存入数组;
5、计算数组中每个数乘普通数的进位,加入高一位数组;
6、输出时先计算使用了多少个的数组,然后向前输出数组。
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 int a[8001],n;
int a[8001],n;
 int main()
int main()


 {
{
 while(scanf("%d",&n)!=EOF)
    while(scanf("%d",&n)!=EOF)

 
     {
{
 int i,j;
        int i,j;
 memset(a,0,sizeof(a));
        memset(a,0,sizeof(a));
 for(i=2,a[0]=1;i<=n;i++)
        for(i=2,a[0]=1;i<=n;i++)

 
         {
{
 for(j=0;j<8000;j++) a[j]*=i;
            for(j=0;j<8000;j++) a[j]*=i;    
 for(j=0;j<8000;j++)
            for(j=0;j<8000;j++)

 
             {
{
 a[j+1]+=a[j]/100000;
                a[j+1]+=a[j]/100000;
 a[j]%=100000;
                a[j]%=100000;
 }
            }
 }
        }    
 for(i=8000;i>=0&&!a[i];i--);
        for(i=8000;i>=0&&!a[i];i--);
 printf("%d",a[i--]);
        printf("%d",a[i--]);
 for(;i>=0;i--) printf("%05d",a[i]);
        for(;i>=0;i--) printf("%05d",a[i]);
 printf("\n");
        printf("\n");
 }
    }
 return 0;
    return 0;
 }
}posted @ 
2010-10-31 14:32 wuxu 阅读(2340) | 
评论 (2) | 
编辑 收藏 
			posted @ 
2010-09-22 12:12 wuxu 阅读(260) | 
评论 (0) | 
编辑 收藏题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1609
方法一:转化为求一维最长上升子序列。O(nlogn)
 #include<iostream>
#include<iostream>
 #include<algorithm>
#include<algorithm>
 using namespace std;
using namespace std;
 int b[10005];
int b[10005];
 int n;
int n;
 typedef struct node
typedef struct node


 {
{
 int l,m;
    int l,m;
 bool operator<(node t)
    bool operator<(node t)

 
     {
{
 if(l<t.l) return 1;
         if(l<t.l) return 1;
 else if(l==t.l&&m<t.m) return 1;
         else if(l==t.l&&m<t.m) return 1;
 else return 0;
         else return 0;
 }
    }
 }block;
}block;
 block a[10005];
block a[10005];
 int LIS()
int LIS()


 {
{
 int L=0;
    int L=0;
 for(int i=1;i<=n;i++)
    for(int i=1;i<=n;i++)

 
     {
{
 int ll=1,rr=L;
         int ll=1,rr=L;
 while(ll<=rr)
         while(ll<=rr)

 
          {
{
 int mid=(ll+rr)/2;
            int mid=(ll+rr)/2;
 if(b[mid]<=a[i].m) ll=mid+1;
            if(b[mid]<=a[i].m) ll=mid+1;
 else rr=mid-1;
            else rr=mid-1;
 }
         }  
 b[ll]=a[i].m;
         b[ll]=a[i].m;
 if(ll>L) L++;
         if(ll>L) L++;
 }
    }
 return L;
    return L;
 }
}
 int main()
int main()


 {
{
 while(scanf("%d",&n)!=EOF&&n)
    while(scanf("%d",&n)!=EOF&&n)

 
     {
{
 for(int i=1;i<=n;i++)
        for(int i=1;i<=n;i++)
 scanf("%d%d",&a[i].l,&a[i].m);
        scanf("%d%d",&a[i].l,&a[i].m);
 sort(a+1,a+n+1);
        sort(a+1,a+n+1);
 printf("%d\n",LIS());
        printf("%d\n",LIS());
 }
    }
 printf("*\n");
    printf("*\n");
 return 0;
    return 0;
 }
}

方法二:状态转移方程为:f[i][j]=max{f[i-1][j],f[i][j-1]}+a[i][j].
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 #define max(x,y) (x>y?x:y)
#define max(x,y) (x>y?x:y)
 int a[105][105],f[105][105];
int a[105][105],f[105][105];

 int main()
int main()


 {
{
 int n;
    int n;
 while(scanf("%d",&n)!=EOF&&n)
    while(scanf("%d",&n)!=EOF&&n)

 
     {
{
 int i,j,k,s;
        int i,j,k,s;
 memset(a,0,sizeof(a));
        memset(a,0,sizeof(a));
 memset(f,-1,sizeof(f));
        memset(f,-1,sizeof(f));
 f[0][0]=0;
        f[0][0]=0;
 f[0][1]=0;
        f[0][1]=0;
 f[1][0]=0;
        f[1][0]=0;
 int xx=0,yy=0;
        int xx=0,yy=0;
 for(i=1;i<=n;i++)
        for(i=1;i<=n;i++)

 
         {
{
 scanf("%d%d",&k,&s);
            scanf("%d%d",&k,&s);
 if(xx<k) xx=k;
            if(xx<k) xx=k;
 if(yy<s) yy=s;
            if(yy<s) yy=s;
 a[k][s]++;
            a[k][s]++;
 }
        }
 for(i=1;i<=xx;i++)
        for(i=1;i<=xx;i++)
 for(j=1;j<=yy;j++)
            for(j=1;j<=yy;j++)

 
             {
{
 if(f[i-1][j]!=-1)
                if(f[i-1][j]!=-1)
 f[i][j]=max(f[i][j],f[i-1][j]+a[i][j]);
                    f[i][j]=max(f[i][j],f[i-1][j]+a[i][j]);
 if(f[i][j-1]!=-1)
                if(f[i][j-1]!=-1)
 f[i][j]=max(f[i][j],f[i][j-1]+a[i][j]);
                    f[i][j]=max(f[i][j],f[i][j-1]+a[i][j]);
 }
            }
 int ans=0;
       int ans=0;
 for(i=1;i<=xx;i++)
       for(i=1;i<=xx;i++)
 for(j=1;j<=yy;j++)
           for(j=1;j<=yy;j++)
 if(ans<f[i][j]) ans=f[i][j];
               if(ans<f[i][j]) ans=f[i][j];
 printf("%d\n",ans);
       printf("%d\n",ans);
 }
    }
 printf("*\n");
    printf("*\n");
 return 0;
    return 0;
 }
}

posted @ 
2010-09-07 21:08 wuxu 阅读(668) | 
评论 (0) | 
编辑 收藏
			O(n^2)代码:
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 int h[40000],d[40000];
int h[40000],d[40000];
 int main()
int main()


 {
{
 int test=0;
    int test=0;
 while(1)
    while(1)

 
     {
{
 int i,j,k;
        int i,j,k;
 test++;
        test++;
 scanf("%d",&h[1]);
        scanf("%d",&h[1]);
 if(h[1]==-1) break;
        if(h[1]==-1) break;
 k=1;
        k=1;
 while(scanf("%d",&j)!=EOF&&j!=-1)
        while(scanf("%d",&j)!=EOF&&j!=-1)

 
         {
{
 h[++k]=j;
             h[++k]=j;
 }
        }
 h[0]=40000;
        h[0]=40000;
 memset(d,0,sizeof(d));
        memset(d,0,sizeof(d));
 for(i=1;i<=k;i++)
        for(i=1;i<=k;i++)
 for(j=0;j<i;j++)
        for(j=0;j<i;j++)
 if(h[j]>h[i]&&d[j]+1>d[i])
        if(h[j]>h[i]&&d[j]+1>d[i])
 d[i]=d[j]+1;
        d[i]=d[j]+1;
 
        
 int ans=0;
        int ans=0;
 for(i=1;i<=k;i++)
        for(i=1;i<=k;i++)
 if(d[i]>ans) ans=d[i];
        if(d[i]>ans) ans=d[i]; 
 if(test!=1) printf("\n");
        if(test!=1) printf("\n");
 printf("Test #%d:\n",test);
        printf("Test #%d:\n",test);
 printf("  maximum possible interceptions: %d\n",ans);
        printf("  maximum possible interceptions: %d\n",ans);
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

O(nlogn)代码:

 /**//*============================*\
/**//*============================*\
 最长下降子序列 O(nlogn)
  最长下降子序列 O(nlogn) 
 \*============================*/
\*============================*/
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 const int inf=1000000;
const int inf=1000000;
 int a[30000],b[30000];//b[i]表示长度为i的下降序列中,末尾数最大的那个序列的代表。
int a[30000],b[30000];//b[i]表示长度为i的下降序列中,末尾数最大的那个序列的代表。 
 int n;
int n;

 int lds()
int lds()


 {
{
 int ans=0;
    int ans=0;
 b[0]=inf;
    b[0]=inf;
 for(int i=1;i<=n;i++)
    for(int i=1;i<=n;i++)

 
     {
{
 int l=1,r=ans;
        int l=1,r=ans;
 while(l<=r)       //找l最小的b[l],使b[l]<=a[i].
        while(l<=r)       //找l最小的b[l],使b[l]<=a[i]. 

 
         {
{
 int t=(l+r)/2;
            int t=(l+r)/2;
 if(b[t]>a[i]) l=t+1;
            if(b[t]>a[i]) l=t+1;
 else r=t-1;
            else r=t-1;
 }
        }
 b[l]=a[i];
        b[l]=a[i];
 if(l>ans) ans++;
        if(l>ans) ans++;        
 }
    }
 return ans;
    return ans;
 }
}

 int main()
int main()


 {
{
 int test=0;
    int test=0;
 while(scanf("%d",&a[1])!=EOF&&a[1]!=-1)
    while(scanf("%d",&a[1])!=EOF&&a[1]!=-1)

 
     {
{
 int i,t;
        int i,t;
 n=1;
        n=1;
 test++;
        test++;
 while(scanf("%d",&t)!=EOF&&t!=-1)
        while(scanf("%d",&t)!=EOF&&t!=-1)
 a[++n]=t;
        a[++n]=t;
 if(test!=1) printf("\n");
        if(test!=1) printf("\n");
 printf("Test #%d:\n",test);
        printf("Test #%d:\n",test);
 printf("  maximum possible interceptions: %d\n",lds());
        printf("  maximum possible interceptions: %d\n",lds());
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

posted @ 
2010-09-06 20:05 wuxu 阅读(438) | 
评论 (0) | 
编辑 收藏
			题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4007很好的一道题目,用f[i,j]表示前i个学生分为j个班时的最小unhappy值,状态转移方程为:f[i,j]=min{f[k,j-1],+(sum[i]-sum[k])*g[j]}.其中a<=i-k<=b,sum[i] = sigma {(x[s] -L)^2 | s≤ i}.
但现在的时间复杂度为O(k*n^2),显然会TLE。将转移方程整理一下:f[i,j]=sum[i]*g[j]+min{f[k,j-1]-sum[k]*g[j]}. 显然可维护一个单调递增队列,每次转移之前将新的可选状态从队列尾插入,同时保证队列头的元素在可选范围之内。这样每次转移就可以只取队列头的元素,总的时间复杂度为O(n*k).
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 const long long inf=100000000000000ll;
const long long inf=100000000000000ll;
 long long sum[10005],aver;
long long sum[10005],aver;
 long long f[10005][205];
long long f[10005][205];
 int x[10005],g[205];
int x[10005],g[205];
 int n,m,a,b;
int n,m,a,b;
 typedef struct
typedef struct


 {
{
 long long unhap;
   long long unhap;
 int loc;
   int loc;
 }node;
}node;
 node q[10005];
node q[10005];

 int main()
int main()


 {
{
 int test=0;
    int test=0;
 while(scanf("%d%d%d%d",&n,&m,&a,&b)!=EOF)
    while(scanf("%d%d%d%d",&n,&m,&a,&b)!=EOF)

 
     {
{
 test++;
         test++;
 aver=0;
         aver=0;
 int i,j;
         int i,j;
 for(i=1;i<=n;i++)
         for(i=1;i<=n;i++)

 
          {
{
 scanf("%d",&x[i]);
              scanf("%d",&x[i]);
 aver+=x[i];
              aver+=x[i];
 }
         }
 aver/=n;
         aver/=n;
 for(i=1;i<=m;i++)
         for(i=1;i<=m;i++)
 scanf("%d",&g[i]);
         scanf("%d",&g[i]);
 sum[0]=0;
         sum[0]=0;
 for(i=1;i<=n;i++)
         for(i=1;i<=n;i++)
 sum[i]=sum[i-1]+(x[i]-aver)*(x[i]-aver);
         sum[i]=sum[i-1]+(x[i]-aver)*(x[i]-aver);
 for(i=0;i<=n;i++)
         for(i=0;i<=n;i++)
 for(j=0;j<=m;j++)
         for(j=0;j<=m;j++)
 f[i][j]=inf;
         f[i][j]=inf;
 f[0][0]=0;
         f[0][0]=0;
 long long ans_unhap=inf;
         long long ans_unhap=inf;
 int ans_k=m+1,ans_t=n+1;
         int ans_k=m+1,ans_t=n+1;
 for(j=1;j<=m;j++)
         for(j=1;j<=m;j++)

 
          {
{
 int head=0,tail=0;
              int head=0,tail=0;
 for(i=a;i<=n;i++)
              for(i=a;i<=n;i++)

 
               {
{
 node temp;
                   node temp;
 if(f[i-a][j-1]!=inf)
                   if(f[i-a][j-1]!=inf)

 
                    {
{
 temp.unhap=f[i-a][j-1]-sum[i-a]*g[j];
                        temp.unhap=f[i-a][j-1]-sum[i-a]*g[j];
 temp.loc=i-a;
                        temp.loc=i-a;
 while(head<tail&&q[tail-1].unhap>=temp.unhap) tail--;  //用>=是为了保证最后一个班的学生在多解的情况下人数最少。
                        while(head<tail&&q[tail-1].unhap>=temp.unhap) tail--;  //用>=是为了保证最后一个班的学生在多解的情况下人数最少。 
 q[tail].unhap=temp.unhap;
                        q[tail].unhap=temp.unhap;
 q[tail++].loc=temp.loc;
                        q[tail++].loc=temp.loc;
 }
                   }
 while(head<tail&&q[head].loc<i-b) head++;
                   while(head<tail&&q[head].loc<i-b) head++;
 if(head<tail) f[i][j]=q[head].unhap+sum[i]*g[j];
                   if(head<tail) f[i][j]=q[head].unhap+sum[i]*g[j];
 }
              }
 if(f[n][j]!=inf)  //求多解情况下的最小分班数。
              if(f[n][j]!=inf)  //求多解情况下的最小分班数。 

 
               {
{
 if(ans_unhap>f[n][j])
                   if(ans_unhap>f[n][j])

 
                    {
{
 ans_unhap=f[n][j];
                        ans_unhap=f[n][j];
 ans_k=j;
                        ans_k=j;
 ans_t=n-q[head].loc;
                        ans_t=n-q[head].loc;
 }
                   }
 }
              }
 }
         }
 if(test!=1) printf("\n");
         if(test!=1) printf("\n");
 if(ans_unhap==inf) printf("No solution.\n");
         if(ans_unhap==inf) printf("No solution.\n");
 else printf("%lld %d %d",ans_unhap,ans_k,ans_t);
         else printf("%lld %d %d",ans_unhap,ans_k,ans_t);
 }
    }
 return 0;
    return 0;
 }
}

 
			posted @ 
2010-09-04 22:40 wuxu 阅读(417) | 
评论 (0) | 
编辑 收藏
			简单DP      题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3127
状态转移方程:f[i,j]=max{f[i,j],f[i-a,j]+f[a,j-b]+p,f[i,j-b]+f[i-a,b]+p}
                  f[i,j]=max{f[i,j],f[i-b,j]+f[b,j-a]+p,f[i,j-a]+f[i-b,a]+p}
 #include<iostream>
#include<iostream>
 #include<algorithm>
#include<algorithm>
 #define max(a,b) (a>b?a:b)
#define max(a,b) (a>b?a:b)
 using namespace std;
using namespace std;
 int test,n,x,y;
int test,n,x,y;
 int f[1005][1005];
int f[1005][1005];
 typedef struct
typedef struct 


 {
{
 int len,wth,val;
   int len,wth,val;
 }CLOTH;
}CLOTH;
 CLOTH c[15];
CLOTH c[15];
 int main()
int main()


 {
{
 scanf("%d",&test);
    scanf("%d",&test);
 while(test--)
    while(test--)

 
     {
{
 scanf("%d%d%d",&n,&x,&y);
         scanf("%d%d%d",&n,&x,&y);
 for(int i=0;i<n;i++)
         for(int i=0;i<n;i++)
 scanf("%d%d%d",&c[i].len,&c[i].wth,&c[i].val);
         scanf("%d%d%d",&c[i].len,&c[i].wth,&c[i].val);
 memset(f,0,sizeof(f));
         memset(f,0,sizeof(f));
 for(int i=1;i<=x;i++)
         for(int i=1;i<=x;i++)
 for(int j=1;j<=y;j++)
         for(int j=1;j<=y;j++)

 
          {
{
 for(int k=0;k<n;k++)
              for(int k=0;k<n;k++)

 
               {
{
 int a=c[k].len;
                  int a=c[k].len;
 int b=c[k].wth;
                  int b=c[k].wth;
 if(i>=a&&j>=b)
                  if(i>=a&&j>=b)

 
                   {
{
 f[i][j]=max(f[i][j],f[i-a][j]+f[a][j-b]+c[k].val);
                       f[i][j]=max(f[i][j],f[i-a][j]+f[a][j-b]+c[k].val);
 f[i][j]=max(f[i][j],f[i][j-b]+f[i-a][b]+c[k].val);
                       f[i][j]=max(f[i][j],f[i][j-b]+f[i-a][b]+c[k].val);
 }
                  }
 swap(a,b);
                  swap(a,b);
 if(i>=a&&j>=b)
                  if(i>=a&&j>=b)

 
                   {
{
 f[i][j]=max(f[i][j],f[i-a][j]+f[a][j-b]+c[k].val);
                       f[i][j]=max(f[i][j],f[i-a][j]+f[a][j-b]+c[k].val);
 f[i][j]=max(f[i][j],f[i][j-b]+f[i-a][b]+c[k].val);
                       f[i][j]=max(f[i][j],f[i][j-b]+f[i-a][b]+c[k].val);
 }
                  }
 }
              }
 }
         }
 printf("%d\n",f[x][y]);
         printf("%d\n",f[x][y]);
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

posted @ 
2010-08-29 10:38 wuxu 阅读(320) | 
评论 (0) | 
编辑 收藏
以求最大值为例,设f[i,j]表示以i为起点,长度为2^j这个区间中的最大值,即[i,i+2^j-1]这个区间内的最大值,那么在询问[a,b]区间的最大值时答案就是max(f[a,k], f[b-2^k+1,k]),其中k是满足2^k<=b-a的最大的k,即k=ln(b-a+1)/ln(2);另外,这两个区间必须覆盖[a,b].
f的求法可以用动态规划,f[i,j]=max(f[i,j-1],f[i+2^(j-1),j-1]).
题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3264
 #include<iostream>
#include<iostream>
 #include<cmath>
#include<cmath>
 #define max(a,b) (a>b?a:b)
#define max(a,b) (a>b?a:b)
 #define min(a,b) (a<b?a:b)
#define min(a,b) (a<b?a:b) 
 using namespace std;
using namespace std;
 int n,q,a,b;
int n,q,a,b;
 int h[50005];
int h[50005];
 int maxn[50005][16];
int maxn[50005][16];
 int minn[50005][16];
int minn[50005][16];
 void st_init()
void st_init()


 {
{
 for(int i=1;i<=n;i++)
     for(int i=1;i<=n;i++) 
 maxn[i][0]=minn[i][0]=h[i];
     maxn[i][0]=minn[i][0]=h[i];
 int m=int(log(double(n))/log(2.0));
     int m=int(log(double(n))/log(2.0));
 for(int i=1;i<=m;i++)
     for(int i=1;i<=m;i++)
 for(int j=1;j<=n;j++)
     for(int j=1;j<=n;j++)

 
      {
{
 maxn[j][i]=maxn[j][i-1];
          maxn[j][i]=maxn[j][i-1];
 if(j+(1<<(i-1))<=n)
          if(j+(1<<(i-1))<=n) 
 maxn[j][i]=max(maxn[j][i],maxn[j+(1<<(i-1))][i-1]);
          maxn[j][i]=max(maxn[j][i],maxn[j+(1<<(i-1))][i-1]);
 }
     }
 
     
 for(int i=1;i<=m;i++)
     for(int i=1;i<=m;i++)
 for(int j=1;j<=n;j++)
     for(int j=1;j<=n;j++)

 
      {
{
 minn[j][i]=minn[j][i-1];
          minn[j][i]=minn[j][i-1];
 if(j+(1<<(i-1))<=n)
          if(j+(1<<(i-1))<=n)
 minn[j][i]=min(minn[j][i],minn[j+(1<<(i-1))][i-1]);
          minn[j][i]=min(minn[j][i],minn[j+(1<<(i-1))][i-1]);
 }
     }    
 }
}
 int st_search(int l,int r)
int st_search(int l,int r)


 {
{
 int m=int(log(double(r-l+1))/log(2.0));
    int m=int(log(double(r-l+1))/log(2.0));
 int mx=max(maxn[l][m],maxn[r-(1<<m)+1][m]);
    int mx=max(maxn[l][m],maxn[r-(1<<m)+1][m]);
 int mn=min(minn[l][m],minn[r-(1<<m)+1][m]);
    int mn=min(minn[l][m],minn[r-(1<<m)+1][m]);
 return mx-mn;
    return mx-mn;
 }
}
 int main()
int main()


 {
{
 scanf("%d%d",&n,&q);
    scanf("%d%d",&n,&q);
 for(int i=1;i<=n;i++)
    for(int i=1;i<=n;i++)
 scanf("%d",&h[i]);
    scanf("%d",&h[i]);
 st_init();
    st_init();
 for(int i=1;i<=q;i++)
    for(int i=1;i<=q;i++)

 
     {
{
 scanf("%d%d",&a,&b);
        scanf("%d%d",&a,&b);
 printf("%d\n",st_search(a,b));
        printf("%d\n",st_search(a,b));
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

posted @ 
2010-08-28 13:29 wuxu 阅读(231) | 
评论 (0) | 
编辑 收藏
			题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3401用f[i][j]表示第i天股票数为j的最大收益,f[i][j]可以从以下三个地方得到:
1、在上次交易的基础上再买一些: f[i][j]=max{f[i][j],f[r][k]-(j-k)*b_price[i]} 0<r<i-w, 0<=j-k<=b_num[i]
2、在上次交易的基础上卖出一些: f[i][j]=max{f[i][j],f[r][k]+(k-j)*s_price[i]} 0<r<i-w, 0<=k-j<=s_num[i]
3、当天股票不动: f[i][j]=max{f[i][j],f[i-1][j]}
这样的时间复杂度为O(T^2*MaxP^2),需要做一些优化.
对于买股票的时候,f[r][k]-(j-k)*b_price[i]=f[r][k]+k*b_price[i]-j*b_price[i] ,(j>= k>=j-b_num[i]),f[i][j]的最优值由f[r][k]+k*b_price[i]确定,由递推方程可知,f[r][k]始终是股票数为k的最大值.  对于某个j,f[r][k]+k*b_price[i]已经重复求过了,这次只需要求f[r][j]+j*b_price[i]即可,因此可以用单调队列来保存这些信息,并且可以方便的取出最大值。  卖股票的情况也同上面类似。此时的时间复杂度为O(T*MaxT).
 #include<iostream>
#include<iostream>
 #define max(a,b) (a>b?a:b)
#define max(a,b) (a>b?a:b)
 using namespace std;
using namespace std;
 const int inf=0x7fffffff;
const int inf=0x7fffffff;
 int test,t,maxp,w;
int test,t,maxp,w;
 int b_price[2005],s_price[2005];
int b_price[2005],s_price[2005];
 int b_num[2005],s_num[2005];
int b_num[2005],s_num[2005];
 int f[2005][2005];
int f[2005][2005];
 typedef struct node
typedef struct node


 {
{
 int mon,num;
    int mon,num;
 }NODE;
}NODE;
 NODE q[2005];
NODE q[2005];
 int main()
int main()


 {
{
 scanf("%d",&test);
    scanf("%d",&test);
 while(test--)
    while(test--)

 
     {
{
 scanf("%d%d%d",&t,&maxp,&w);
        scanf("%d%d%d",&t,&maxp,&w);
 for(int i=1;i<=t;i++)
        for(int i=1;i<=t;i++)
 scanf("%d%d%d%d",&b_price[i],&s_price[i],&b_num[i],&s_num[i]);
        scanf("%d%d%d%d",&b_price[i],&s_price[i],&b_num[i],&s_num[i]);
 for(int i=0;i<=t;i++)
        for(int i=0;i<=t;i++)
 for(int j=0;j<=maxp;j++)
        for(int j=0;j<=maxp;j++)
 f[i][j]=-inf;
        f[i][j]=-inf;
 for(int i=1;i<=w+1;i++)
        for(int i=1;i<=w+1;i++)
 for(int j=0;j<=maxp&&j<=b_num[i];j++)
        for(int j=0;j<=maxp&&j<=b_num[i];j++)
 f[i][j]=-j*b_price[i];
        f[i][j]=-j*b_price[i];
 for(int i=2;i<=w+1;i++)
        for(int i=2;i<=w+1;i++)
 for(int j=0;j<=maxp;j++)
        for(int j=0;j<=maxp;j++)
 f[i][j]=max(f[i-1][j],f[i][j]);
        f[i][j]=max(f[i-1][j],f[i][j]);
 
        
 for(int i=w+2;i<=t;i++)
        for(int i=w+2;i<=t;i++)

 
         {
{
 int head=0,tail=0;
            int head=0,tail=0;
 for(int j=0;j<=maxp;j++)
            for(int j=0;j<=maxp;j++)

 
             {
{
 f[i][j]=max(f[i][j],f[i-1][j]);
                 f[i][j]=max(f[i][j],f[i-1][j]);
 int pre=i-w-1;
                 int pre=i-w-1;
 int money=f[pre][j]+j*b_price[i];
                 int money=f[pre][j]+j*b_price[i];
 while(head<tail&&q[tail-1].mon<money) tail--;
                 while(head<tail&&q[tail-1].mon<money) tail--;
 q[tail].mon=money;
                 q[tail].mon=money;
 q[tail++].num=j;
                 q[tail++].num=j;
 while(head<tail&&j-q[head].num>b_num[i]) head++;
                 while(head<tail&&j-q[head].num>b_num[i]) head++;
 f[i][j]=max(f[i][j],q[head].mon-j*b_price[i]);
                 f[i][j]=max(f[i][j],q[head].mon-j*b_price[i]);
 }
            }
 head=tail=0;
            head=tail=0;
 for(int j=maxp;j>=0;j--)
            for(int j=maxp;j>=0;j--)

 
             {
{
 int pre=i-w-1;
                 int pre=i-w-1;
 int money=f[pre][j]+j*s_price[i];
                 int money=f[pre][j]+j*s_price[i];
 while(head<tail&&q[tail-1].mon<money) tail--;
                 while(head<tail&&q[tail-1].mon<money) tail--;
 q[tail].mon=money;
                 q[tail].mon=money;
 q[tail++].num=j;
                 q[tail++].num=j;
 while(head<tail&&q[head].num-j>s_num[i]) head++;
                 while(head<tail&&q[head].num-j>s_num[i]) head++;
 f[i][j]=max(f[i][j],q[head].mon-j*s_price[i]);
                 f[i][j]=max(f[i][j],q[head].mon-j*s_price[i]);
 }
            }
 }
        }
 int ans=-inf;
        int ans=-inf;
 for(int i=0;i<=maxp;i++)
        for(int i=0;i<=maxp;i++)
 if(f[t][i]>ans) ans=f[t][i];
        if(f[t][i]>ans) ans=f[t][i];
 printf("%d\n",ans);
        printf("%d\n",ans);
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

posted @ 
2010-08-27 18:38 wuxu 阅读(631) | 
评论 (1) | 
编辑 收藏
			题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3560题意:求连通分量的个数和环图的个数。如果是环图那么每个点的度数应该为2。
 #include<iostream>
#include<iostream>
 using namespace std;
using namespace std;
 typedef struct
typedef struct


 {
{
 int v;
    int v;
 int next;
    int next;
 }edge;
}edge;
 edge e[600005];
edge e[600005];
 int head[100005];
int head[100005];
 int deg[100005];
int deg[100005];
 bool vis[100005];
bool vis[100005];
 int n,m,num1,num2;
int n,m,num1,num2;
 void bfs(int u)
void bfs(int u)


 {
{
 num1++;
     num1++;
 vis[u]=1;
     vis[u]=1;
 bool flag=0;
     bool flag=0;
 int front=0,rear=0;
     int front=0,rear=0;
 int q[100005];
     int q[100005];
 q[rear++]=u;
     q[rear++]=u;
 if(deg[u]!=2) flag=1;
     if(deg[u]!=2) flag=1;
 while(front<rear)
     while(front<rear)

 
      {
{
 int x=q[front++];
         int x=q[front++];
 for(int i=head[x];i!=-1;i=e[i].next)
         for(int i=head[x];i!=-1;i=e[i].next)

 
          {
{
 if(!vis[e[i].v])
             if(!vis[e[i].v])

 
              {
{
 vis[e[i].v]=1;
                 vis[e[i].v]=1;
 if(deg[e[i].v]!=2) flag=1;
                 if(deg[e[i].v]!=2) flag=1;
 q[rear++]=e[i].v;
                 q[rear++]=e[i].v;
 }
             }
 }
         }
 }
     }
 if(!flag) num2++;
     if(!flag) num2++;
 }
}
 int main()
int main()


 {
{
 while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m))

 
     {
{
 int i,j,uu,vv,tot=0;
        int i,j,uu,vv,tot=0;
 memset(head,-1,sizeof(head));
        memset(head,-1,sizeof(head));
 memset(deg,0,sizeof(deg));
        memset(deg,0,sizeof(deg));
 memset(vis,0,sizeof(vis));
        memset(vis,0,sizeof(vis));
 for(i=0;i<m;i++)
        for(i=0;i<m;i++)

 
         {
{
 scanf("%d%d",&uu,&vv);
            scanf("%d%d",&uu,&vv);
 deg[uu]++;
            deg[uu]++;
 deg[vv]++;
            deg[vv]++;
 
            
 e[tot].v=vv;
            e[tot].v=vv;
 e[tot].next=head[uu];
            e[tot].next=head[uu];
 head[uu]=tot++;
            head[uu]=tot++;
 
            
 e[tot].v=uu;
            e[tot].v=uu;
 e[tot].next=head[vv];
            e[tot].next=head[vv];
 head[vv]=tot++;
            head[vv]=tot++;
 }
        }
 
        
 num1=0,num2=0;
        num1=0,num2=0;
 for(i=0;i<n;i++)
        for(i=0;i<n;i++)
 if(!vis[i])
        if(!vis[i])
 bfs(i);
        bfs(i);
 
        
 printf("%d %d\n",num1,num2);
        printf("%d %d\n",num1,num2);
 }
    }
 //system("pause");
    //system("pause");
 return 0;
    return 0;
 }
}

posted @ 
2010-08-25 18:55 wuxu 阅读(405) | 
评论 (2) | 
编辑 收藏