NOI2009[变换序列/transform]

膜拜了题解后写的,我是用的倒序匹配,如果想知道该怎么做,推荐看看这份题解

CODE:

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-5-13

DESCRIPTION:

$DESCRIPTION

*/

#include <cstdio>

using std::FILE;

using std::fopen;

using std::fclose;

using std::fscanf;

using std::fprintf;

#include <cstring>

using std::memset;

 

class Application

{

      static const int MAXN=10000;

      static const int MAXDEGREE=2;

      static const int NOTMATCHED=-1;

      FILE* in;

      FILE* out;

      int N;

      int D[MAXN];

      int degree[MAXN];

      int edge[MAXN][MAXDEGREE];

      int match[MAXN*2];

      bool visited[MAXN*2];

      void addEdge(int u,int v)

      {

           edge[u][degree[u]++]=v+N;

      }

      void build_graph()

      {

           for (int i=0;i<N;i++)

           {

               int n=(i+D[i])%N;

               int m=(i-D[i]+N)%N;

               if (n==m) addEdge(i,n);

               else if (n<m)

               {

                    addEdge(i,n);

                    addEdge(i,m);

               }

               else if (n>m)

               {

                    addEdge(i,m);

                    addEdge(i,n);

               }

           }

      }

      bool find(int x)

      {

           for (int i=0,y;i<degree[x];i++)

               if (!visited[y=edge[x][i]])

               {

                  visited[y]=true;

                  if (match[y]==NOTMATCHED||find(match[y]))

                  {

                     match[x]=y;

                     match[y]=x;

                     return true;

                  }

               }

           return false;

      }

      public:

      Application(const char* input,const char* output)

                        :in(fopen(input,“r”)),out(fopen(output,“w”))

      {

                        fscanf(in,“%d”,&N);

                        for (int i=0;i<N;i++) fscanf(in,“%d”,D+i);

                        memset(degree,0,sizeof(degree));

                        memset(match,NOTMATCHED,sizeof(match));

      }

      ~Application()

      {

                    fclose(in);

                    fclose(out);

      }

      int run()

      {

          build_graph();

          for (int i=N;memset(visited,0,sizeof(visited)),i–;)

              if (!find(i))

              {

                 fprintf(out,“No Answer\n”);

                 return 0;

              }

          for (int i=0;i<N;i++)

              fprintf(out,“%d%c”,match[i]-N,i+1==N?’\n’:’ ‘);

          return 0;

      }

};

 

int main()

{

    Application app(“transform.in”,“transform.out”);

    return app.run();

}

 

UVA100[The 3n + 1 problem]

就是简单模拟,加记忆化,加线段树加速查询。


恩,注意输入中i和j不保证i<=j,就是这个让我WA2次。


CODE:


/*


PROGRAM: $PROGRAM


AUTHOR: Su Jiao


DATE: 2010-5-13


DESCRIPTION:


$DESCRIPTION


*/


#include <stdio.h>


#define MAXN 1000000


 


int f[MAXN+2];


int st[MAXN<<2];


 


int max(int a,int b)


{


    return a>b?a:b;


}


void build_segment_tree(int L=1,int R=MAXN,int root=1)


{


     if (L==R) st[root]=f[L];


     else


     {


         int LL=L,LR=(L+R)>>1,Lroot=root<<1;


         int RL=LR+1,RR=R,Rroot=Lroot|1;


         build_segment_tree(LL,LR,Lroot);


         build_segment_tree(RL,RR,Rroot);


         st[root]=max(st[Lroot],st[Rroot]);


     }


}


int get_max(int l,int r,int L=1,int R=MAXN,int root=1)


{


    if (r<L||l>R) return 0;


    if (l<=L&&R<=r) return st[root];


    else


    {


        int LL=L,LR=(L+R)>>1,Lroot=root<<1;


        int RL=LR+1,RR=R,Rroot=Lroot|1;


        return max(get_max(l,r,LL,LR,Lroot),


                   get_max(l,r,RL,RR,Rroot));


    }


}


 


int main()


{


    f[1]=1;


    for (int i=2;i<=MAXN;i++)


    {


        long long int n=i;


        int step=0;


        for (;;)


        {


            if (n<=MAXN&&f[n])


            {


               step+=f[n];


               break;


            }


            step++;


            if (n&1) n=((n<<1)|1)+n;


            else n>>=1;


        }


        f[i]=step;


    }


    build_segment_tree();


    int i,j;


    while (scanf(“%d%d”,&i,&j)!=EOF)


          if (i<=j) printf(“%d %d %d\n”,i,j,get_max(i,j));


          else printf(“%d %d %d\n”,i,j,get_max(j,i));


    return 0;


}


 


 

夜的随想

微风,细雨。
漫步,街头。
看城市风光。
灯光,不微弱,很耀眼,不喜欢。
人,来往,
忙的,茫的,或盲的,
不喜欢。
我只身一人,走着,却不知走向何处。
我可能是迷路了。
可是,然后,我要找找方向。
看天上,北极星正在睡觉;看地下,还是一步一步地走吧。
世上本没有多少路,
迷路的人多了,
路也跟着多了。
或许路就是用来迷的吧。

夜深人静,梦很轻。
风一吹便漂泊到很美的远方。
远方的梦是我的方向。
行走,眺望。

耀眼的灯光,
它想要照亮的是,
一片无尽的黑暗。
一片黑暗,
只是想掩饰,
夜空里的星光。
星空,
真的好美,
却只在故乡。


夜深邃,人憔悴。
讨厌的聚会。
会不会,有些愧。
害我不能睡。

APIO2010

感觉这次考试的题目和USACO上的Elite 2010 U S Open Competition很像,第一题动规,第二题可以树规,第三题更是惊人的只是加了一个外壳!

不过鉴于本人那次USACO的月赛考挂了,所以这次也考得不理想。恩,总共120分。

恩,这份题解都是依靠大牛们的解题思路来弄的,可能思路写得有点短而代码又写得很长,恩,将就看吧。

第一题是动态规划,加斜率优化(感谢RJ和LJL让我知道世上还有这么神奇的东西)。

恩,动规方程是f[i]=max{f[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c},关于斜率优化,推荐去百度一下[我写了一篇,所以推荐看一下我写的,呵呵,点这里]。

第二题,当K=1时直接最长链,当K=2时,先求一个最长链,然后分两种情况,一种是在去掉先前的最长链上的边后得到的很多小树上再求最长链,另一种是找两棵小树,最大化它们以在链上的点为根时的深度和减去这两个根的距离。

下图描述的是第二种情况,假设黑色的为第一次找到的最长链,则小树A、B、C、D的深度分别为3、3、4、3。然后最优的是选B和C,因为B和C的距离为1,然后3+4-1得6,是max{height(i)+height(j)-distance(i,j),i,j=A|B|C|D and i!=j}。

APIO2010解题报告 - 天之骄子 - 天之骄子的家

第三题不写了,如果有听懂陈丹琦的思路的可以看一下这个这个,主要是第三题的。

恩,贴代码。

CODE:

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-5-13

DESCRIPTION:

$DESCRIPTION

*/

#include <stdio.h>

#define MAXN 1000000

 

int n,a,b,c;

int x[MAXN+2];

long long int sum[MAXN+2];

int head,tail;

int q[MAXN+2];

long long int f[MAXN+2];

long long int answer;

 

double k(int i,int j)

{

       return double(f[i]-f[j]+a*(sum[i]*sum[i]-sum[j]*sum[j])+b*(sum[j]-sum[i]))/double(2*a*(sum[i]-sum[j]));

}

void print_long_long_int(long long int value)

{

     if (value>=10) print_long_long_int(value/10),printf(“%d”,value%10);

     else printf(“%d”,value);

}

bool isNumber[256];

void read(int& who)

{

    char get,flag=’+’;

    if ((get=getchar())==’-‘)

    {

       flag=’-‘;

       who=0;

    }

    else who=get-‘0’;

    while (isNumber[get=getchar()]) who=who*10+get-‘0’;

    if (flag==’-‘) who=-who;

}

int main()

{

    //freopen(“commando.in”,”r”,stdin);

    //freopen(“commando.out”,”w”,stdout);

    isNumber[‘0’]

    =isNumber[‘1’]

    =isNumber[‘2’]

    =isNumber[‘3’]

    =isNumber[‘4’]

    =isNumber[‘5’]

    =isNumber[‘6’]

    =isNumber[‘7’]

    =isNumber[‘8’]

    =isNumber[‘9’]

    =true;

    read(n);

    read(a);

    read(b);

    read(c);

    //scanf(“%d%d%d%d”,&n,&a,&b,&c);

    for (int i=1;i<=n;i++) read(x[i]);//scanf(“%d”,x+i);

    for (int i=1;i<=n;i++)

        sum[i]=sum[i-1]+x[i];

    //f[i]=max{f[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c}

    q[tail]=0;

    for (int i=1;i<=n;i++)

    {

        while (head<tail&&k(q[head],q[head+1])<=sum[i]) head++;

        long long int x=sum[i]-sum[q[head]];

        f[i]=f[q[head]]+(a*x+b)*x+c;

        while (head<tail&&k(q[tail-1],q[tail])>=k(q[tail],i)) tail–;

        q[++tail]=i;

    }

    answer=f[n];

    print_long_long_int(answer);

    printf(“\n”);

    //fclose(stdin);

    //fclose(stdout);

    return 0;

}

 

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-5-13

DESCRIPTION:

$DESCRIPTION

*/

#include <stdio.h>

#include <string.h>

#define MAXN 100000

 

struct Edge{Edge* next;int to;};

int n,K;

Edge* link[MAXN+2];

 

void addEdge(int u,int v)

{

    static int top;

    static Edge pool[(MAXN+2)*2];

    pool[top].next=link[u];

    pool[top].to=v;

    link[u]=pool+top++;

    pool[top].next=link[v];

    pool[top].to=u;

    link[v]=pool+top++;

}

 

int deepest;

int deepest_node;

bool visited[MAXN+2];

void dfs(int node,int depth=0)

{

    if (depth>=deepest)

    {

        deepest=depth;

        deepest_node=node;

    }

    visited[node]=true;

    for (Edge* i=link[node];i;i=i->next)

        if (!visited[i->to])

            dfs(i->to,depth+1);

}

bool marked[MAXN+2];

int top;

int list[MAXN+2];

bool dfs_mark(int node,int target)

{

    visited[node]=true;

    if (node==target) marked[node]=true;

    for (Edge* i=link[node];i;i=i->next)

        if (!visited[i->to])

            if (dfs_mark(i->to,target))

                marked[node]=true;

    if (marked[node]) list[top++]=node;

    return marked[node];

}

void dfs_2nd_circle(int node,int depth=0,int father=0)

{

    if (depth>=deepest)

    {

        deepest=depth;

        deepest_node=node;

    }

    for (Edge* i=link[node];i;i=i->next)

        if (i->to!=father&&!marked[i->to])

            dfs_2nd_circle(i->to,depth+1,node);

}

 

int main()

{

    //freopen(“patrol.in”,”r”,stdin);

    //freopen(“patrol.out”,”w”,stdout);           

    scanf(“%d%d”,&n,&K);

    for (int i=1;i<n;i++)

    {

        int u,v;

        scanf(“%d%d”,&u,&v);

        addEdge(u,v);

    }

    if (K==1)

    {

        memset(visited,0,sizeof(visited));

        deepest=0;

        dfs(1);

        memset(visited,0,sizeof(visited));

        deepest=0;

        dfs(deepest_node);

        printf(“%d\n”,deepest+1+(n-1-deepest)*2);

    }

    else

    {

        int answer_1st,answer_2nd;

        int u,v;

        memset(visited,0,sizeof(visited));

        deepest=0;

        dfs(1);

        u=deepest_node;

        memset(visited,0,sizeof(visited));

        deepest=0;

        dfs(deepest_node);        

        v=deepest_node;

        memset(visited,0,sizeof(visited));

        dfs_mark(v,u);

        answer_1st=deepest;

        //for (int i=1;i<=n;i++)

        //    if (marked[i]) printf(“marked:%d\n”,i);

        answer_2nd=0;

        for (int j=0,i;j<top;j++)

            if (marked[i=list[j]])

            {

                marked[i]=false;

                deepest=0;

                dfs_2nd_circle(i);

                deepest=0;

                dfs_2nd_circle(deepest_node);

                if (deepest>answer_2nd) answer_2nd=deepest;

                marked[i]=true;

                //printf(“deepest:%d\n”,deepest);

            }

        int outer;

        outer=0;

        for (int j=0,i;j<top;j++)

            if (marked[i=list[j]])

            {

                marked[i]=false;

                deepest=0;

                dfs_2nd_circle(i);

                if (deepest+outer>answer_2nd) answer_2nd=deepest+outer;

                outer=(deepest>?outer)-1;

                marked[i]=true;

                //printf(“deepest:%d\n”,deepest);

            }

        printf(“%d\n”,(answer_1st+1+answer_2nd+1)+(n-1-answer_1st-answer_2nd)*2);

    }

    return 0;

}

 

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-5-14

DESCRIPTION:

$DESCRIPTION

*/

#include <stdio.h>

#include <math.h>

#include <utility>

#define MAXN 1500

#define x first

#define y second

#define Point pair<int,int>

#define P(a,b) Point(a,b)

using namespace std;

 

int n;

int x[MAXN+2],y[MAXN+2];

Point p[MAXN+2];

long long int total;

long long int counter;

 

/*

void get(int a,int b,int c)

{

     double xa=x[a],xb=x[b],xc=x[c];

     double ya=y[a],yb=y[b],yc=y[c];

    

     double a1=2*(xb-xa),b1=2*(yb-ya),c1=xa*xa+ya*ya-xb*xb-yb*yb;

     double a2=2*(xc-xa),b2=2*(yc-ya),c2=xa*xa+ya*ya-xc*xc-yc*yc;

    

     double X=-(c1*b2-c2*b1)/(a1*b2-a2*b1);

     double Y=-(c1*a2-c2*a1)/(b1*a2-b2*a1);

     double sqr_dis=(x[a]-X)*(x[a]-X)+(y[a]-Y)*(y[a]-Y);

     for (int d=0;d<n;d++)

         if ((x[d]-X)*(x[d]-X)+(y[d]-Y)*(y[d]-Y)<=sqr_dis+0.01) counter++;

}

*/

struct Compare

{

       static

       inline

       long long int cross(const Point& a,const Point& b)

       {

            return (long long int)(a.x)*(long long int)(b.y)-(long long int)(b.x)*(long long int)(a.y);

       }

       static

       inline

       bool less(const Point& a,const Point& b)

       {

            return cross(a,b)>0;

       }

      

       static

       void sort(Point* l,Point* r)

       {

            Point* i=l;

            Point* j=r;

            Point mid=*(l+((r-l)>>1));

            while (i<=j)

            {

                  while (less(*i,mid)) i++;

                  while (less(mid,*j)) j–;

                  if (i<=j)

                  {

                     Point s=*i;

                     *i=*j;

                     *j=s;

                     i++;

                     j–;

                  }

            }

            if (l<j) sort(l,j);

            if (i<r) sort(i,r);

       }

      

};

long long int C(long long int n,long long int m)

{

     if (m>n||m<0) return 0;

     long long int c=1;

     for (int i=1;i<=m;i++) c=c*(n-i+1)/i;

     return c;

}

int count(int O)

{

    Point np[MAXN+2];

    int nn=0;

    for (int i=0;i<n;i++) if (i!=O) np[nn++]=Point(p[i].x-p[O].x,p[i].y-p[O].y);

    Compare compare;

    compare.sort(np,np+nn-1);

    int result=0;

    for (int i=0,j=0;i<nn;i++)

    {

        while (compare.less(np[i],np[(j+1)%nn])) j=(j+1)%nn;

        int get=(j-i+nn)%nn;

        if (get>=2) result+=((get)*(get-1))>>1;//C(get,2);

    }

    return result;

}

 

int main()

{

    //freopen(“signaling.in”,”r”,stdin);

    //freopen(“signaling.out”,”w”,stdout);

    scanf(“%d”,&n);

    for (int i=0;i<n;i++)

        scanf(“%d%d”,x+i,y+i);

    /*

    for (int a=0;a<n;a++)

        for (int b=a+1;b<n;b++)

            for (int c=b+1;c<n;c++)

                get(a,b,c),total++;

    */

    for (int i=0;i<n;i++)

        p[i]=P(x[i],y[i]);

    for (int i=0;i<n;i++)

        counter+=count(i);

    counter+=C(n,4)*2-C(n-1,3)*n;

    total=C(n,3);

    printf(“%f\n”,double(counter)/double(total)+3);

    //fclose(stdin);

    //fclose(stdout);

    return 0;

}

 

信息学知识点分类[信息学资料]

*表示只会用库
+表示不熟悉
?表示待学

数据结构:
 基本数据结构:
  数组
  链表
  栈(STL/stack)
  队列(STL/queue,STL/deque)
  串
  HASH表
 高级数据结构:
  块状链表{数组+链表}
  堆(STL/priority_queue)
  线段树
  并查集
  字典树+
  二叉搜索树+
  左偏树?
  平衡二叉搜索树[AVL?,RBTree?,Treap,Splay?](STL/map,STL/set)
算法:
 通用:
  贪心[矩阵胚+]
  递归,分治,递推
  搜索[DFS,BFS,ID,Astar,IDAstar,最优性剪枝,可行性剪枝]
  动态规划[树形动规,状态压缩+,利用单调性优化,四边形不等式]
 排序:
  冒泡,插入
  快排(STL/sort)
 图论:
  最小生成树[Prim,Kruskal]
  最短路[Dijkstra,SPFA(Bellman-Ford),Floyd]
  网络流-最大流[Edmonds-Karp,ISAP,Dinic,Relabel-to-front]
  网络流-费用流[SPFA增广]
  有向图强联通分量[Tarjan]
  拓扑排序
  匈牙利算法
  欧拉路,欧拉回路
  树的直径
  最小环[Floyd]
  最近公共祖先,LCA[RMQ],Tarjan
 计算几何:
  凸包[Graham]
  半平面交[朴素O(n^2),分治?]
 字符串匹配:
  KMP
  AC自动机
  后缀数组
  Rabin-Karp
 博弈论:
  Nim取石子游戏
  SG函数
  敌对搜索
 数论:
  辗转相除
  扩展辗转相除
 计数问题:
  生成函数+
  排列组合
  容斥原理
  抽屉原理
  置换群?
 代数:
  高斯消元
  高精度数

最美的天是蓝的,但现在已是黑夜。 
有的只是蓝色的梦,还有没有星光的夜空。 
我躺在草丛,望着远方。 
远方什么也没有。 
只听得旁人的嬉笑打闹,和我独自听着的歌。 
想大声叫,却不忍心破坏这难得的宁静。 
宁静的别人,宁静的我。 
在这里的我们,是否都厌倦了喧闹。 
然后才想起也有这样一个去处。 
才想起曾经在夜里那总是数不清的星星。 
还有那些美梦。

NOI2009[植物大战僵尸/pvz]

恩,在做题的时候玩了一次植物大战僵尸。

然后,这道题是最大权闭合图。

还有注意将一定不会被攻击的植物从图中丢掉。

推荐读一下2007年国家集训队论文(胡伯涛《最小割模型在信息学竞赛中的应用》)。

CODE:

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-4-28

DESCRIPTION:

$DESCRIPTION

*/

#include <stdio.h>

#include <string.h>

#include <vector>

#include <queue>

using std::vector;

#define P std::pair<int,int>

#define Q std::priority_queue<P>

 

#define min(a,b) ((a)<(b)?(a):(b))

#define max(a,b) ((a)>(b)?(a):(b))

 

const int MAXN=20+1,MAXM=30+1,oo=~(1<<31);

int N,M;

int score[MAXN*MAXM];

vector<int> protect[MAXN*MAXM];

int c[MAXN*MAXM+2][MAXN*MAXM+2];

bool can_attack[MAXN*MAXM+2];

int indegree[MAXN*MAXM+2];

 

void get_attack()

{

     for (int i=0;i<N*M;i++)

        for (int j=0;j<protect[i].size();j++)

            indegree[protect[i][j]]++;

    

     int open=0,close=0;

     int q[MAXN*MAXM+2];

     for (int i=0;i<N*M;i++)

         if (!indegree[i])

            q[open++]=i;

    

     while (close<open)

     {

           can_attack[q[close]]=true;

           for (int j=0;j<protect[q[close]].size();j++)

           {

               indegree[protect[q[close]][j]]–;

               if (!indegree[protect[q[close]][j]])

                  q[open++]=protect[q[close]][j];

           }

           close++;

     }

}

 

int h[MAXN*MAXM+2],vh[MAXN*MAXM+2];

int n,augc;

int flow;

bool found;

void aug(int m)

{

     int i,augco,minh;

     minh=n-1;

     augco=augc;

     if (m==n)

     {

        found=true;

        flow+=augc;

        return;

     }

     for (i=1;i<=n;i++)

         if (c[m][i]>0)

         {

            if (h[m]==h[i]+1)

            {

               if (c[m][i]<augc) augc=c[m][i];

               aug(i);

               if (h[1]>=n) return;

               if (found) break;

               augc=augco;

            }

            if (h[i]<minh) minh=h[i];

         }

     if (!found)

     {

        vh[h[m]]–;

        if (vh[h[m]]==0) h[1]=n;

        h[m]=minh+1;

        vh[h[m]]++;

     }

     else

     {

         c[m][i]-=augc;

         c[i][m]+=augc;

     }

    

}

int max_flow(int S,int T) //SAP

{

    int d[MAXN*MAXM+2][MAXN*MAXM+2];

    memcpy(d,c,sizeof(d));

    n=N*M+2;

    for (int i=0;i<n;i++)

    {

        if (i!=0&&i!=S)

        {

        d[i][0]=c[i][S];

        d[0][i]=c[S][i];

        d[i][S]=c[i][0];

        d[S][i]=c[0][i];

        }

    }

    d[S][0]=c[0][S];

    d[0][S]=c[S][0];

    d[0][0]=c[S][S];

    d[S][S]=c[0][0];

    for (int i=1;i<=n;i++)

        for (int j=1;j<=n;j++)

            c[i][j]=d[i-1][j-1];

    vh[0]=n;

    while (h[1]<n)

    {

          augc=oo;

          found=false;

          aug(1);

    }

    return flow;

}

/*

int max_flow(int S,int T) //preflow-push

{

    const int L=0,R=N*M+1;

    static int flow=0;

    static int f[MAXN*MAXM+2][MAXN*MAXM+2];

    //memset(f,0,sizeof(f));

   

    static int h[MAXN*MAXM+2];

    //BFS

    {

        static int open=0,close=0;

        static int q[MAXN*MAXM+2];

        static bool inq[MAXN*MAXM+2];

        //memset(inq,0,sizeof(inq));

        inq[q[open++]=T]=true;

        h[T]=0;

        while (close<open)

        {

              int now=q[close++];

              for (int next=L;next<=R;next++)

                  if ((f[next][now]<c[next][now])&&(!inq[next]))

                  {

                     inq[q[open++]=next]=true;

                     h[next]=h[now]+1;

                     //printf(“h[%d(next)]=%d\n”,next,h[next]);

                  }

        }

    }

    h[S]=N*M+2;

   

    static int e[MAXN*MAXM+2];

    //memset(e,0,sizeof(e));

    for (int i=L;i<=R;i++)

        if (f[S][i]<c[S][i])

        {

           e[i]+=c[S][i];

           f[S][i]+=c[S][i];

           f[i][S]-=c[S][i];

           e[S]-=c[S][i];

        }

    for (;;)

    {

        bool find=false;

        for (int i=L;i<=R;i++)

            if (e[i]>0&&i!=S&&i!=T)

            {

               find=true;

               for (int j=L;j<=R;j++)

                   if (h[i]==h[j]+1&&f[i][j]<c[i][j])

                   {

                      //Push

                      int p=min(e[i],c[i][j]-f[i][j]);

                      //printf(“push(%d,%d) :%d\n”,i,j,p);

                      e[j]+=p;

                      f[i][j]+=p;

                      f[j][i]-=p;

                      e[i]-=p;

                   }

               if (e[i])

               {

                  int minh=h[i];

                  for (int j=L;j<=R;j++)

                      if (f[i][j]<c[i][j])

                         minh=min(minh,h[j]);

                  h[i]=minh+1;

               }

            }

        if (!find) break;

    }

    flow=e[T];

    //printf(“flow:%d\n”,flow);

    return flow;

}

*/

/*

int max_flow(int S,int T) //shortest-augument

{

    int L=0,R=N*M+1;

    int flow=0;

    int f[MAXN*MAXM+2][MAXN*MAXM+2];

    memset(f,0,sizeof(f));

    int d[MAXN*MAXM+2];

    //BFS

    {

        int open=0,close=0;

        int q[MAXN*MAXM+2];

        bool inq[MAXN*MAXM+2];

        memset(inq,0,sizeof(inq));

        inq[q[open++]=T]=true;

        d[T]=0;

        while (close<open)

        {

              int now=q[close++];

              for (int next=L;next<=R;next++)

                  if ((f[next][now]<c[next][now])&&(!inq[next]))

                  {

                     inq[q[open++]=next]=true;

                     d[next]=d[now]+1;

                  }

        }

    }

    int pre[MAXN*MAXM+2];

    int i=S,j;

    while (d[S]<M*N+2)

    {

          bool find=false;

          for (j=L;j<=R;j++)

              if (f[i][j]<c[i][j]&&d[i]==d[j]+1)

              {

                 find=true;

                 break;

              }

          if (find)

          {

             pre[j]=i;

             i=j;

             if (i==T)

             {

                int inc=oo;

                int u;

                u=T;

                do

                {

                  inc=min(inc,c[pre[u]][u]-f[pre[u]][u]);

                  u=pre[u];

                }

                while (u!=S);

                flow+=inc;

                u=T;

                do

                {

                  f[pre[u]][u]+=inc;

                  f[u][pre[u]]-=inc;

                  u=pre[u];

                }

                while (u!=S);

                i=S;

             }

          }

          else

          {

              d[i]=N*M+2;

              for (j=L;j<=R;j++)

                  if (f[i][j]<c[i][j])

                     d[i]=min(d[i],d[j]+1);

              if (i!=S) i=pre[i];

          }

    }

    //printf(“flow:%d\n”,flow);

    return flow;   

}

*/

/*

int max_flow(int S,int T) //Edmonds-Karp + Priority Queue

{

    int L=0,R=N*M+1;

    int flow=0;

    int f[MAXN*MAXM+2][MAXN*MAXM+2];

    memset(f,0,sizeof(f));

    for (;;)

    {

        Q q;

        bool inq[MAXN*MAXM+2];

        memset(inq,0,sizeof(inq));

        int val[MAXN*MAXM+2];

        int pre[MAXN*MAXM+2];

       

        val[S]=oo;

        pre[S]=S;

        q.push(P(val[S],S));

        inq[S]=true;

       

        while ((!inq[T])&&(!q.empty()))

        {

              int now=q.top().second;

              q.pop();

              for (int next=L;next<=R;next++)

                  if ((f[now][next]<c[now][next])&&(!inq[next]))

                  {

                     val[next]=min(val[now],c[now][next]-f[now][next]);

                     pre[next]=now;

                     q.push(P(val[next],next));

                     inq[next]=true;

                  }

        }

        if (inq[T])

        {

           flow+=val[T];

           int u=T;

           while (pre[u]!=u)

           {

                 f[pre[u]][u]+=val[T];

                 f[u][pre[u]]-=val[T];

                 u=pre[u];

           }

        }

        else break;

    }

    //printf(“flow:%d\n”,flow);

    return flow;

}

*/

/*

int max_flow(int S,int T) //Edmonds-Karp

{

    int L=0,R=N*M+1;

    int flow=0;

    int f[MAXN*MAXM+2][MAXN*MAXM+2];

    memset(f,0,sizeof(f));

    for (;;)

    {

        int open=0,close=0;

        int q[MAXN*MAXM+2];

        bool inq[MAXN*MAXM+2];

        memset(inq,0,sizeof(inq));

        int val[MAXN*MAXM+2];

        int pre[MAXN*MAXM+2];

       

        inq[q[open++]=S]=true;

        val[S]=oo;

        pre[S]=S;

       

        while (!inq[T]&&(close<open))

        {

              int now=q[close++];

              for (int next=L;next<=R;next++)

                  if ((f[now][next]<c[now][next])&&(!inq[next]))

                  {

                     inq[q[open++]=next]=true;

                     val[next]=min(val[now],c[now][next]-f[now][next]);

                     pre[next]=now;

                     if (next==T) break;

                  }

        }

        if (inq[T])

        {

           flow+=val[T];

           int u=T;

           while (pre[u]!=u)

           {

                 f[pre[u]][u]+=val[T];

                 f[u][pre[u]]-=val[T];

                 u=pre[u];

           }

        }

        else break;

    }

    //printf(“flow:%d\n”,flow);

    return flow;

}

*/

int main()

{

    freopen(“pvz.in”,“r”,stdin);

    freopen(“pvz.out”,“w”,stdout);

   

    scanf(“%d%d”,&N,&M);

    for (int i=0;i<N*M;i++)

    {

        int r,c,p;

        scanf(“%d”,score+i);

        r=i/M;

        c=i%M;

        if (c>0) protect[i].push_back(r*M+c-1);

        scanf(“%d”,&p);

        while (p–)

        {

              scanf(“%d%d”,&r,&c);

              protect[i].push_back(r*M+c);

        }

    }

    get_attack();

    int total=0;

    int S=N*M,T=N*M+1;

    for (int i=0;i<M*N;i++)

    {

        if (can_attack[i]&&score[i]>0)

            total+=(c[S][i]=score[i]);

        else if (can_attack[i]&&score[i]<0)

             c[i][T]=-score[i];

    }   

    for (int i=0;i<M*N;i++)

        for (int j=0;j<protect[i].size();j++)

            if (can_attack[i]&&can_attack[protect[i][j]])

               c[protect[i][j]][i]=oo;

    printf(“%d\n”,total-max_flow(S,T));

    fclose(stdin);

    fclose(stdout);

    return 0;

}

 

USACO[Elite 2010 March Competition/gold]starc

恩,星际很好玩,上周就和高一以及高二竞赛班的同学玩了一天(不过我很菜)。

当然,我们玩游戏是为了对这道题了解更加深入。O(∩_∩)O哈哈~。

然后,就是半平面交了。

用已知信息进行半平面交,得出可行域。

然后线性规划。

如果最优都小于零或最差都大于零则判断。

否则不可判断。

CODE:

/*

PROG: starc

LANG: C++

ID: boleyn.2

*/

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-4-27

DESCRIPTION:

TITLE: StarCowraft [Jaehyun Park/KOI 2007, 2010]

CONTENT:

The beta version of StarCowraft II is ready! Farmer John and Bessie

are testing it, trying different strategies in one-on-one battles

against each other’s armies. The goal in StarCowraft II is to defeat

your opponent’s army in a battle.

Each player’s army fights in a battle. An army comprises as many

as three different types of ‘units’ with respective strengths denoted

by constant positive real numbers unknown to the players: cattlebruisers

with strength S1, cow templars with strength S2, and ultracows with

strength S3. The only given bounding information is that no unit

is more than 100 times as strong as any another unit.

An army’s total strength is the sum of the individual strengths of

each of its units. An army that has, among others units, 23

cattlebruisers would gain 23*S1 strength just from the cattlebruisers.

When two opposing armies fight in a battle, the army with a higher

total strength value wins.  If the armies have exactly equal strength

values, one of the players randomly wins.

Farmer John and Bessie played N (0 <= N <= 300) “test battles”. In

the i-th test battle, FJ’s army had J1_i cattlebruisers, J2_i cow

templars, and J3_i ultracows (0 <= J1_i + J2_i + J3_i <= 1,000).

Similarly, Bessie’s army had B1_i cattlebruisers, B2_i cow templars,

and B3_i ultracows (0 <= B1_i + B2_i + B3_i <= 1,000). After their

armies fought against each other, FJ and Bessie recorded the winner

as a single ‘victory letter’ V_i: “J” if Farm John won the battle;

“B” if Bessie won.

Although these victory results are the only information that they

have, they hope to predict some of the results of additional battles

if they are given the unit compositions of two opposing armies. For

some battles, though, they know it might not be possible to determine

the winner with certainty.

Given the results of the N test battles that Farmer John and Bessie

already played, write a program that decides the winner (if possible)

for M (1 <= M <= 2,000) new battles.

The results reported for the test battles are correct; there exists

at least one set of strength values which are consistent with the

results.

For purposes of demonstrating the army strength evaluation functions,

consider these test battles fought in a game where we (but neither

FJ nor Bessie) know that S1=9.0, S2=7.0, and S3=4.0:

   —- Farmer John —-    ——- Bessie ——    Battle

   J1  J2  J3 J_Strength    B1  B2  B3 B_Strength   Outcome

    6   5   4    105         5   4   7    101          J

    5   4   2     81         3   5   5     82          B

    9   0  10    121         8   2   7    114          J

These results connote the following deduced results for the reasons

shown:

   —- Farmer John —-    ——- Bessie ——    Battle

   J1  J2  J3 J_Strength    B1  B2  B3 B_Strength   Outcome

    6   6   4    112         5   4   7    101          J

              FJ’s army is even stronger than in test battle 1

    9   0  10    121         8   2   6    110          J

              Bessie’s army is even weaker than in test battle 3

PROBLEM NAME: starc

INPUT FORMAT:

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: Line i+1 describes a test battle with seven

        space-separated items — a victory letter and six

        space-separated integer unit counts: V_i, J1_i, J2_i, J3_i,

        B1_i, B2_i, and B3_i

* Lines N+2..N+M+1: Line i+N+1 describes a “new battle” using six

        space-separated integers: J1_i, J2_i, J3_i, B1_i, B2_i, and

        B3_i

SAMPLE INPUT (file starc.in):

3 3

J 6 5 4 5 4 7

B 5 4 2 3 5 5

J 9 0 10 8 2 7

6 6 4 5 4 7

9 0 10 8 2 6

3 4 8 4 4 6

OUTPUT FORMAT:

* Lines 1..M: Line i contains the outcome of the i-th new battle: “J”

        if Farmer John definitely wins, “B” if Bessie definitely wins,

        and “U” (undecidable) if it is impossible to decide the winner

        with the given information.

SAMPLE OUTPUT (file starc.out):

J

J

U

OUTPUT DETAILS:

First two games correspond to the examples in the description. The

result of the last game cannot be determined with only the information

that Farmer John and Bessie currently have. Specifically, both S_1=9.0,

S_2=7.0, S_3=4.0 and S_1=12.0, S_2=20.0, S_3=10.0 are consistent with the

“test battles,” but they give different results when plugged in the third

“new battle.”

*/

#include <stdio.h>

#include <vector>

using namespace std;

 

#define Point pair<double,double>

#define x first

#define y second

#define P make_pair

#define Polygon vector<Point>

 

const double MAXRATIO=100;

const double ZERO=1e-10;

int N,M;

Polygon polygon;

 

char getf(double a,double b,double c,Point p)

{

     double f=a*p.x+b*p.y+c;

     //printf(“a=%.2f,b=%.2f,c=%.2f\n”,a,b,c);

     //printf(“P(%.2f,%.2f)\n”,p.x,p.y);

     //printf(“f:%.8f\n”,f);

     if (f<-ZERO) return ‘J’;

     if (f>ZERO) return ‘B’;

     return ‘U’;

}

Point intersection(double a,double b,double c,Point p1,Point p2)

{

      double f1=a*p1.x+b*p1.y+c;

      double f2=a*p2.x+b*p2.y+c;

      return P((f2*p1.x-f1*p2.x)/(f2-f1),(f2*p1.y-f1*p2.y)/(f2-f1));

}

void cut(int a,int b,int c,char f)

{

     Polygon get;

     for (int i=0;i<polygon.size();i++)

         if (getf(a,b,c,polygon[i])==f)

            get.push_back(polygon[i]);

         else

         {

             int before,next;

             if (i) before=i-1;

             else before=polygon.size()-1;

             if (i+1!=polygon.size()) next=i+1;

             else next=0;

             if (getf(a,b,c,polygon[before])==f)

                get.push_back(intersection(a,b,c,polygon[before],polygon[i]));

             if (getf(a,b,c,polygon[next])==f)

                get.push_back(intersection(a,b,c,polygon[i],polygon[next]));

         }

     polygon.swap(get);

}

char check(int a,int b,int c)

{

     bool getJ=false;

     bool getB=false;

     for (int i=0;i<polygon.size();i++)

     {

         char f=getf(a,b,c,polygon[i]);

         if (f==’U’) return ‘U’;

         if (f==’J’) getJ=true;

         if (f==’B’) getB=true;

         if (getJ&&getB) return ‘U’;

     }

     if (getJ) return ‘J’;

     if (getB) return ‘B’;

}

int main()

{

    freopen(“starc.in”,“r”,stdin);

    freopen(“starc.out”,“w”,stdout);

    scanf(“%d %d\n”,&N,&M);

    polygon.push_back(P(1.0/MAXRATIO,1.0/MAXRATIO));

    polygon.push_back(P(1.0/MAXRATIO,MAXRATIO));

    polygon.push_back(P(MAXRATIO,MAXRATIO));

    polygon.push_back(P(MAXRATIO,1.0/MAXRATIO));

    cut(-MAXRATIO,1,0,’J’);

    cut(1,-MAXRATIO,0,’J’);

    for (int i=0;i<N;i++)

    {

        char f;

        int a1,b1,c1,a2,b2,c2;

        scanf(“%c %d %d %d %d %d %d\n”,&f,&a1,&b1,&c1,&a2,&b2,&c2);

        int a=a2-a1,b=b2-b1,c=c2-c1;

        cut(a,b,c,f);

        //for (int i=0;i<polygon.size();i++)

        //    printf(“P(%.2f,%.2f)\n”,polygon[i].x,polygon[i].y);

        //printf(“\n”);

    }

    for (int i=0;i<M;i++)

    {

        int a1,b1,c1,a2,b2,c2;

        scanf(“%d %d %d %d %d %d\n”,&a1,&b1,&c1,&a2,&b2,&c2);

        int a=a2-a1,b=b2-b1,c=c2-c1;

        printf(“%c\n”,check(a,b,c));

    }

    fclose(stdin);

    fclose(stdout);

    return 0;

}

 

USACO[Elite 2010 March Competition/gold]balloc

恩,贪心+线段树维护。

CODE:

/*

PROG: balloc

LANG: C++

ID: boleyn.2

*/

/*

PROGRAM: $PROGRAM

AUTHOR: Su Jiao

DATE: 2010-4-27

DESCRIPTION:

TITLE: Barn Allocation [Jaehyun Park/Jeffrey Wang, 2010]

CONTENT:

Farmer John recently opened up a new barn and is now accepting stall

allocation requests from the cows since some of the stalls have a

better view of the pastures.

The barn comprises N (1 <= N <= 100,000) stalls conveniently numbered

1..N; stall i has capacity C_i cows (1 <= C_i <= 100,000). Cow i

may request a contiguous interval of stalls (A_i, B_i) in which to

roam (1 <= A_i <= N; A_i <= B_i <= N), i.e., the cow would like to

wander among all the stalls in the range A_i..B_i (and the stalls

must always have the capacity for her to wander).

Given M (1 <= M <= 100,000) stall requests, determine the maximum

number of them that can be satisfied without exceeding stall

capacities.

Consider both a barn with 5 stalls that have the capacities shown

and a set cow requests:

Stall id:    1   2   3   4   5

           +—+—+—+—+—+

Capacity:  | 1 | 3 | 2 | 1 | 3 | 

           +—+—+—+—+—+

Cow 1       XXXXXXXXXXX             (1, 3)

Cow 2           XXXXXXXXXXXXXXX     (2, 5)

Cow 3           XXXXXXX             (2, 3)

Cow 4                   XXXXXXX     (4, 5)

FJ can’t satisfy all four cows, since there are too many requests

for stalls 3 and 4.

Noting that Cow 2 requests an interval that includes stalls 3 and

4, we test the hypothesis that cows 1, 3, and 4 can have their

requested stalls. No capacity is exceeded, so the answer for this

set of data is 3 — three cows (1, 3, and 4) can have their requests

satisfied.

MEMORY LIMIT: 32 MB

TIME LIMIT: 2 seconds

PROBLEM NAME: balloc

INPUT FORMAT:

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: Line i+1 contains a single integer: C_i

* Lines N+2..N+M+1: Line i+N+1 contains two integers: A_i and B_i

SAMPLE INPUT (file balloc.in):

5 4

1

3

2

1

3

1 3

2 5

2 3

4 5

OUTPUT FORMAT:

* Line 1: The maximum number of requests that can be satisfied

SAMPLE OUTPUT (file balloc.out):

3

*/

#include <stdio.h>

 

#define MAXN 100000

#define MAXM 100000

#define oo ~(1<<31)

 

int N,M;

int C[MAXN+1];

int A[MAXM],B[MAXM];

int answer;

int st_min[MAXN<<2],st_cnt[MAXN<<2];

 

void quick_sort(int L,int R)

{

    int mid_A=A[(L+R)>>1];

    int mid_B=B[(L+R)>>1];

    int i=L,j=R;

    while (i<=j)

    {

        while (A[i]<mid_A||(A[i]==mid_A&&B[i]>mid_B)) i++;

        while (A[j]>mid_A||(A[j]==mid_A&&B[j]<mid_B)) j–;

        if (i<=j)

        {

            int swap;

            swap=A[i];

            A[i]=A[j];

            A[j]=swap;

            swap=B[i];

            B[i]=B[j];

            B[j]=swap;

            i++;

            j–;

        }

    }

    if (L<j) quick_sort(L,j);

    if (i<R) quick_sort(i,R);

}

int min(int a,int b)

{

    return a<b?a:b;

}

void build(int L,int R,int root=1)

{

     int LL=L,LR=(L+R)>>1,Lroot=root<<1;

     int RL=LR+1,RR=R,Rroot=Lroot|1;

     if (L==R) st_min[root]=C[L];

     else

     {

         build(LL,LR,Lroot);

         build(RL,RR,Rroot);

         st_min[root]=min(st_min[Lroot],st_min[Rroot]);

     }

     //printf(“[%d,%d] min:%d\n”,L,R,st_min[root]);

}

void update(int L,int R,int root)

{

     int LL=L,LR=(L+R)>>1,Lroot=root<<1;

     int RL=LR+1,RR=R,Rroot=Lroot|1;

     st_cnt[Lroot]+=st_cnt[root];

     st_min[Lroot]-=st_cnt[root];

     st_cnt[Rroot]+=st_cnt[root];

     st_min[Rroot]-=st_cnt[root];

     st_cnt[root]=0;

}

int ask(int l,int r,int L,int R,int root=1)

{

    if (l>R||r<L) return oo;

    if (l<=L&&R<=r) return st_min[root];

    int LL=L,LR=(L+R)>>1,Lroot=root<<1;

    int RL=LR+1,RR=R,Rroot=Lroot|1;

    update(L,R,root);

    return min(ask(l,r,LL,LR,Lroot),ask(l,r,RL,RR,Rroot));

}

void insert(int l,int r,int L,int R,int inc=1,int root=1)

{

     if (l>R||r<L) return;

     if (l<=L&&R<=r)

     {

        st_cnt[root]+=inc;

        st_min[root]-=inc;

        return;

     }

     int LL=L,LR=(L+R)>>1,Lroot=root<<1;

     int RL=LR+1,RR=R,Rroot=Lroot|1;

     update(L,R,root);

     insert(l,r,LL,LR,inc,Lroot);

     insert(l,r,RL,RR,inc,Rroot);

     st_min[root]=min(st_min[Lroot],st_min[Rroot]);

}

 

int main()

{

    freopen(“balloc.in”,“r”,stdin);

    freopen(“balloc.out”,“w”,stdout);

    scanf(“%d %d\n”,&N,&M);

    for (int i=1;i<=N;i++)

        scanf(“%d\n”,&C[i]);

    for (int i=0;i<M;i++)

        scanf(“%d %d\n”,&A[i],&B[i]);

   

    build(1,N);

    quick_sort(0,M-1);

    for (int i=M-1;i>=0;i–)

        if (ask(A[i],B[i],1,N))

           answer++,insert(A[i],B[i],1,N);

   

    printf(“%d\n”,answer);

   

    fclose(stdin);

    fclose(stdout);

    return 0;

}

 

如果有一天

如果有一天,我会好好珍惜这一天,
我希望在这一天里只有快乐相伴。
如果有一天,我的梦想都会实现,
我要和所有朋友分享。
如果有一天,我不知道会不会有这一天,
我只知道时间不停的流逝。
如果有一天,我终将会遇到这一天,
可是,然后呢?
然后,这也将会成为普普通通的一天。
如果那一天,
或许如果那一天永远停留在记忆中会更美。
但是如果真的到了那一天,
那一天,我能做什么?
或许只是一片茫然,
人很多时候在追寻着什么,
但我们真的在追寻什么吗?
我无语。
如果有一天,我希望忘记这一切,
永远留在记忆中,
幸福与美才永恒。

故事里的那一天,
一定不是下雨天,
那是晴天。
蓝天,白云。
艳阳,高照。
和风,吹拂。
吹干了记忆中的伤口。
故事里的那一天,
应该是有故事中的场景,
故事中的你我。
然后,
不会有那些无聊的文字,
有的只是快乐。

可是有一天,
或许即使是笑着,也带着泪。
闪烁的泪光,
掩盖,那些伤痛,
笑,伪装。
唯有清唱着喜欢的歌,
迎接,过去和未来。