抱着好奇心态去开始做APIO的往年试题感受一下难度


Oil

Description

  采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井。被拍卖的整块土地为一个矩形区域,被划分为M×N个小块。 Siruseri地质调查局有关于Navalur土地石油储量的估测数据。这些数据表示为M×N个非负整数,即对每一小块土地石油储量的估计值。 为了避免出现垄断,政府规定每一个承包商只能承包一个由K×K块相连的土地构成的正方形区域。 AoE石油联合公司由三个承包商组成,他们想选择三块互不相交的K×K的区域使得总的收益最大。 例如,假设石油储量的估计值如下: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 8 8 8 8 8 1 1 1 1 8 8 8 8 8 1 1 1 1 8 8 8 8 8 1 1 1 1 1 1 1 8 8 8 1 1 1 1 1 1 1 1 8 8 8 1 1 1 1 1 1 9 9 9 1 1 1 1 1 1 9 9 9 如果K = 2, AoE公司可以承包的区域的石油储量总和为100, 如果K = 3, AoE公司可以承包的区域的石油储量总和为208。 AoE公司雇佣你来写一个程序,帮助计算出他们可以承包的区域的石油储量之和的最大值。

  首先由于是一个个正方形,所以很容易看出最终每块油田所在的区域是通过一些水平或竖直的线隔开的

  并且这些线在它所在的区域内是到达边界的 这道题三个油田也就是最终只可能为下面六种情况

  其中右边的两列看起来比较好处理

  我们只要先预处理左上左下右上右下四个方向最大答案的前缀和

  然后再枚举水平和竖直线的位置

  稍加处理就可以得出答案

  左边的一列以两条水平线为例

  我们枚举一条水平线之后,枚举另一条在它下面的水平线

  这条水平线每向下移一行,中间部分也就多了一行

  所以我们可以预处理出每行每列的最大答案

  在枚举第二条线的时候维护中间部分答案的最大值

  上下部分用前缀和来计算

  在写代码的过程中,由于我统计的是以(x,y)为左上角的边长为k的矩形的答案

  所以前缀和部分用到的时候需要注意哪些地方需要-k+1,哪些地方是限制住的

  时间复杂度O(nm)

 /**************************************************************
    Problem: 1177
    User: mjy0724
    Language: C++
    Result: Accepted
    Time:6128 ms
    Memory:54256 kb
****************************************************************/
 
#include<cstdio>
#include<cstdlib>
#include<cstring>
const int maxn = ;
int a[maxn][maxn],map[maxn][maxn],lu[maxn][maxn],ru[maxn][maxn],ld[maxn][maxn],rd[maxn][maxn],h[maxn],v[maxn];
int max(int a,int b){if (a>b) return a;else return b;}
int main(){
    int n,m,k,ans=;
    scanf("%d%d%d",&n,&m,&k);
    for (int i=;i<=n;i++) for (int j=;j<=m;j++) scanf("%d",&map[i][j]);
    for (int i=;i<=n;i++) for (int j=;j<=m;j++) map[i][j]+=map[i-][j];
    for (int i=;i<=n;i++) for (int j=;j<=m;j++) map[i][j]+=map[i][j-];
    for (int i=;i<=n-k+;i++) for (int j=;j<=m-k+;j++) a[i][j]=map[i+k-][j+k-]-map[i-][j+k-]-map[i+k-][j-]+map[i-][j-];
    for (int i=;i<=n-k+;i++) for (int j=;j<=m-k+;j++) lu[i][j]=max(max(lu[i-][j],lu[i][j-]),a[i][j]);
    for (int i=;i<=n-k+;i++) for (int j=m-k+;j>;j--) ru[i][j]=max(max(ru[i-][j],ru[i][j+]),a[i][j]);
    for (int i=n-k+;i>;i--) for (int j=;j<=m-k+;j++) ld[i][j]=max(max(ld[i+][j],ld[i][j-]),a[i][j]);
    for (int i=n-k+;i>;i--) for (int j=m-k+;j>;j--) rd[i][j]=max(max(rd[i+][j],rd[i][j+]),a[i][j]);
    for (int i=;i<=n;i++) for (int j=;j<=m;j++) h[i]=max(h[i],a[i][j]),v[j]=max(v[j],a[i][j]);
    for (int i=k;i<=n-*k;i++){
        int mx = ;
        for (int j=i+k;j<=n-k;j++){
            mx = max(mx,h[j-k+]);
            ans = max(ans,lu[i-k+][m-k+]+mx+ld[j+][m-k+]);
        }
    }
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m-k;j++) ans=max(ans,lu[i-k+][j-k+]+ru[i-k+][j+]+ld[i+][m-k+]);       
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m-k;j++) ans=max(ans,lu[i-k+][m-k+]+ld[i+][j-k+]+rd[i+][j+]);
 
    for (int i=k;i<=m-*k;i++){
        int mx=;
        for (int j=i+k;j<=m-k;j++){     
            mx = max(mx,v[j-k+]);
            ans = max(ans,lu[n-k+][i-k+]+mx+ru[n-k+][j+]);
        }
    }  
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m-k;j++) ans=max(ans,lu[i-k+][j-k+]+ru[n-k+][j+]+ld[i+][j-k+]);       
    for (int i=k;i<=n-k;i++)
        for (int j=k;j<=m-k;j++) ans=max(ans,lu[n-k+][j-k+]+ru[i-k+][j+]+rd[i+][j+]);         
    printf("%d\n",ans);
    return ;
}

[BZOJ1178]CONVENTION会议中心

Description

Siruseri政府建造了一座新的会议中心。许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议。 对于一个客户而言,仅当在开会时能够独自占用整个会堂,他才会租借会堂。会议中心的销售主管认为:最好的策略应该是将会堂租借给尽可能多的客户。显然,有可能存在不止一种满足要求的策略。 例如下面的例子。总共有4个公司。他们对租借会堂发出了请求,并提出了他们所需占用会堂的起止日期(如下表所示)。 开始日期 结束日期 公司1 4 9 公司2 9 11 公司3 13 19 公司4 10 17 上例中,最多将会堂租借给两家公司。租借策略分别是租给公司1和公司3,或是公司2和公司3,也可以是公司1和公司4。注意会议中心一天最多租借给一个公司,所以公司1和公司2不能同时租借会议中心,因为他们在第九天重合了。 销售主管为了公平起见,决定按照如下的程序来确定选择何种租借策略:首先,将租借给客户数量最多的策略作为候选,将所有的公司按照他们发出请求的顺序编号。对于候选策略,将策略中的每家公司的编号按升序排列。最后,选出其中字典序最小1的候选策略作为最终的策略。 例中,会堂最终将被租借给公司1和公司3:3个候选策略是{(1,3),(2,3),(1,4)}。而在字典序中(1,3)<(1,4)<(2,3)。 你的任务是帮助销售主管确定应该将会堂租借给哪些公司。

  这道题我觉得非常有意思,用一些简单的算法拼凑出了一个很好的解题思路,虽然代码复杂度略高

  首先第一问的答案很显然...直接贪心就可以出解

  我们可以考虑两段时间区间,如果其中一段包含另一段,那么显然这条长的线段是没有用的

  因为在每条线段对答案的贡献都=1的情况下,选这条短的能为其他线段的摆放留有更多空间

  我们把所有的这种不优秀的线段都删除掉以后,将它们按左端点从小到大排序之后

  会发现右端点也是升序,因为否则就会出现包含的情况

  可以考虑取了某条线段i以后,实际上下一条取哪条线段已经确定了

  因为在可以取的范围(左端点大于线段i的右端点)的线段集合中,我们肯定取那个右端点最小的

  由于我们上面得出左端点与右端点同时上升,二分找出第一个左端点大于线段i右端点的线段就是下一条要取的线段

  这样一来好像忽然明白了:其实只要确定了起点,整个要取的线段序列都是确定的

  我们可以用倍增来储存第i条线段接下去要取的第2^j条线段

  直接按照题目的要求来,从小到大去试

  只要当前线段能够放下(即在此之前的线段没有覆盖到这条线段所在的位置)

  咦那为什么不能让之前的移一下呢?我们的顺序是从小到大,人家的优先级比你要高

  所以这样做有一个比较好的性质:确定了的就不能修改

  另外,还要保证放下了之后最优解不变,我们设当前线段所在的空白位置向左右延伸到的最远处分别是lx,rx,当前线段(l,r)

  那么ans(lx,rx)=ans(l,lx-1)+ans(r+1,rx)+1才能够保证最优解不变

  那么获取答案的函数ans如何求得呢?

  上上段我们处理好了倍增的数组,ans即求一个给定起点和终点的线段区间的答案

  直接用倍增处理就可以了

 /**************************************************************
    Problem: 1178
    User: mjy0724
    Language: C++
    Result: Accepted
    Time:5804 ms
    Memory:85588 kb
****************************************************************/
 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
const int maxn=,INF=;
struct point{
    int x,y;
}a[maxn],c[maxn],p[maxn];
struct tree{
    int l,r,lx,rx,cov;
}tr[maxn*];
int n,tot,fa[maxn][],ans,as[maxn],d[maxn],e[maxn];
bool vis[maxn];
char s[];
int max(int a,int b){
    if (a>b) return a;
    else return b;
}
 
int min(int a,int b){
    if (a<b) return a;
    else return b;
}
 
void sortf(int l,int r){
    int i=l,j=r,mid=(l+r) >> ,midx=a[mid].x,midy=a[mid].y;
    do{
        while (i<r&&((a[i].x>midx)||(a[i].x==midx&&a[i].y<midy))) i++;
        while (l<j&&((a[j].x<midx)||(a[j].x==midx&&a[j].y>midy))) j--;
        if (i<=j){
            a[]=a[i];a[i]=a[j];a[j]=a[];
            i++;j--;
        }
    }while (i<=j);
    if (i<r) sortf(i,r);
    if (l<j) sortf(l,j);
}
 
void sortg(int l,int r){
    int i=l,j=r,mid=p[(l+r) >> ].x;
    do{
        while (i<r&&p[i].x<mid) i++;
        while (l<j&&p[j].x>mid) j--;
        if (i<=j){
            p[]=p[i];p[i]=p[j];p[j]=p[];
            i++;j--;
        }
    }while (i<=j);
    if (i<r) sortg(i,r);
    if (l<j) sortg(l,j);
}
 
int find(int x){
    int ans=,l=,r=tot;
    while (l<=r){
        int mid=(l+r) >> ;
        if (p[mid].x>=x){
            ans=mid;r=mid-;
        }else l=mid+;
    }
    return ans;
}
void solve(){
    int minr=INF;
    memset(vis,true,sizeof(vis));
    int j;
    for (int i=;i<=n;i=j){
        for (j=i;a[i].x==a[j].x&&j<=n;j++){
            if (minr<a[j].y) vis[j]=false;
            if (a[j].y<minr) minr=a[j].y;
        }
    }
    tot=;
    for (int i=;i<=n;i++) if (vis[i]) p[++tot]=a[i];
    sortg(,tot);
    for (int i=;i<=tot;i++) fa[i][]=find(p[i].y+);
    for (int j=;( << j)<=n;j++)
        for (int i=;i<=tot;i++) fa[i][j]=fa[fa[i][j-]][j-];
}
 
void build(int p,int l,int r){
    tr[p].l=l;tr[p].r=r;tr[p].lx=INF;tr[p].rx=-INF;tr[p].cov=;
    if (l!=r){
        int mid = (l+r) >> ;
        build(p<<,l,mid);build((p<<)+,mid+,r);
    }
}
 
void sorth(int l,int r){
    int i=l,j=r,mid=d[(l+r) >> ];
    do{
        while (i<r&&d[i]<mid) i++;
        while (l<j&&d[j]>mid) j--;
        if (i<=j){
            int tem=d[i];d[i]=d[j];d[j]=tem;
            i++;j--;
        }
    }while (i<=j);
    if (i<r) sorth(i,r);
    if (l<j) sorth(l,j);
}
 
void ls(){
    for (int i=;i<=n;i++){
        d[++d[]]=a[i].x;d[++d[]]=a[i].y;
    }
    sorth(,d[]);
    int j;
    for (int i=;i<=d[];i=j){
        e[++e[]]=d[i];j=i+;
        while (j<=d[]&&d[i]==d[j]) j++;
    }
}
 
void insert(int p,int l,int r){
    if (tr[p].cov) {tr[p].lx=tr[p].l,tr[p].rx=tr[p].r;}
    if (tr[p].l==l&&tr[p].r==r){
        tr[p].cov=;tr[p].lx=tr[p].l;tr[p].rx=tr[p].r;
        return;
    }
    int mid = (tr[p].l+tr[p].r) >> ;
    if (tr[p].cov) tr[p<<].cov=,tr[(p<<)+].cov=;
    if (r<=mid) insert(p<<,l,r);else
        if (l>mid) insert((p<<)+,l,r);else{
            insert(p<<,l,mid);insert((p<<)+,mid+,r);
        }  
    tr[p].lx=min(tr[p<<].lx,tr[(p<<)+].lx);
    tr[p].rx=max(tr[p<<].rx,tr[(p<<)+].rx); 
}
 
int getnum(int x){
    int l=,r=e[];
    while (l<=r){
        int mid=(l+r) >> ;
        if (e[mid]==x) return mid;
        if (x<e[mid]) r=mid-;else l=mid+;
    }
}
 
int getl(int p,int l,int r){
    if (tr[p].cov){tr[p].lx=l;tr[p].rx=r;}
    if (tr[p].l==l&&tr[p].r==r) return tr[p].lx;
    int mid=(tr[p].l+tr[p].r) >> ;
    if (tr[p].cov) tr[p<<].cov=,tr[(p<<)+].cov=;
    if (r<=mid) return getl(p<<,l,r);else
        if (l>mid) return getl((p<<)+,l,r); else
            return min(getl(p<<,l,mid),getl((p<<)+,mid+,r));
}
 
int getr(int p,int l,int r){
    if (tr[p].cov){tr[p].lx=l;tr[p].rx=r;}
    if (tr[p].l==l&&tr[p].r==r) return tr[p].rx;
    int mid=(tr[p].l+tr[p].r)>>;
    if (tr[p].cov) tr[p<<].cov=,tr[(p<<)+].cov=;
    if (r<=mid) return getr(p<<,l,r);else
        if (l>mid) return getr((p<<)+,l,r);else
            return max(getr(p<<,l,mid),getr((p<<)+,mid+,r));
}
 
int query(int x,int y){
    if (x<||y<||x>e[]||y>e[]) return ;
    int s=-,l=,r=tot;
    while (l<=r){
        int mid=(l+r) >> ;
        if (p[mid].x>=e[x]) s=mid,r=mid-;else l=mid+;
    }
    int t=-;
    l=;r=tot;
    while (l<=r){
        int mid=(l+r) >> ;
        if (p[mid].y<=e[y]) t=mid,l=mid+;else r=mid-;
    }
    if (s==-||t==-||s>t) return ;
    int ans=,i=log(tot)/log();
    while (s<t&&i>=){
        while (s<t&&fa[s][i]!=&&fa[s][i]<=t) s=fa[s][i],ans+=<<i;
        i--;
    }
    return ans;
}
 
int main(){
    scanf("%d",&n);
    for (int i=;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),gets(s);
    for (int i=;i<=n;i++) c[i].x=a[i].x,c[i].y=a[i].y;
    ls();
    sortf(,n);
    solve();   
    build(,,e[]+);
    insert(,,);insert(,e[]+,e[]+);
    for (int i=;i<=n;i++) c[i].x=getnum(c[i].x),c[i].y=getnum(c[i].y); 
    for (int i=;i<=n;i++) if (getl(,c[i].x,c[i].y)==INF&&getr(,c[i].x,c[i].y)==-INF){    
        int ll=getr(,,c[i].x-),rr=getl(,c[i].y+,e[]+);  
        if (query(ll+,rr-)==query(ll+,c[i].x-)+query(c[i].y+,rr-)+) {
        as[++ans]=i;insert(,c[i].x,c[i].y);
        }      
    }
     
    printf("%d\n",ans);
    for (int i=;i<=ans;i++) printf("%d ",as[i]);
    return ;  
}

[BZOJ1179]Atm

Description

  这大概是这套题目中最简单的一道了...

  首先我们可以看出,题目中说的,可以经过一条边多次其实就是要处理环的情况

  取款机里的钱都是非负整数,能拿的没有理由不要

  因此如果进入了一个环,就可以把环中所有的钱都取光,然后从任意一个点出去

  思路已经很明确了,tarjan缩点,同时累计每一个环的现金总数和是否存在一个酒吧

  缩完点的图我们重新连上边(自环不连),就变成了一个有向无环图

  我们可以用拓扑序DP来解决这个问题

  对于给定的起点,这样类似的题目之前也做过

  我的做法是先从起点开始dfs一次,重新统计入度

  然后再进行DP,最后在那些有酒吧坐落的环或点答案中挑出一个最大的输出

 /**************************************************************
    Problem: 1179
    User: mjy0724
    Language: C++
    Result: Accepted
    Time:6804 ms
    Memory:52260 kb
****************************************************************/
 
#include<cstdio>
#include<cstdlib>
#include<cstring>
const int maxn = ;
int cnt,time,top,n,m,s,p,e,fa[maxn],next[maxn],link[maxn],x[maxn],y[maxn],b[maxn];
int stack[maxn],low[maxn],dfn[maxn],pos[maxn],a[maxn],w[maxn],opt[maxn],f[maxn];
bool vis[maxn],ins[maxn],isp[maxn],isbar[maxn];
 
void add(int x,int y){
    fa[++e]=y;next[e]=link[x];link[x]=e;
}
 
int min(int a,int b){
    if (a<b) return a;
    return b;
}
 
int max(int a,int b){
    if (a>b) return a;
    return b;
}
void tarjan(int p){
    dfn[p]=low[p]=++time;stack[++top]=p;
    vis[p]=false;ins[p]=true;
    for (int i=link[p];i!=;i=next[i])
    if (vis[fa[i]]){
        tarjan(fa[i]);
        low[p]=min(low[p],low[fa[i]]);
    }else if (ins[fa[i]]) low[p]=min(low[p],dfn[fa[i]]);
    if (low[p]==dfn[p]){
        cnt++;
        do{
            pos[stack[top]]=cnt;
            a[cnt]+=w[stack[top]];
            isbar[cnt]=isbar[cnt] or isp[stack[top]];              
            ins[stack[top--]]=false;       
        }while (stack[top+]!=p);
    }
}
 
void dfs(int p){
    vis[p]=false;
    for (int i=link[p];i;i=next[i]){
        b[fa[i]]++;
        if (vis[fa[i]]) dfs(fa[i]);
    }
}
 
void solve(int s){
    int head=,tail=;opt[]=s;f[s]=a[s];
    while (head!=tail){
        int x=f[opt[++head]];
        for (int i=link[opt[head]];i;i=next[i]){
            f[fa[i]]=max(f[fa[i]],x+a[fa[i]]);
            b[fa[i]]--;
            if (!b[fa[i]]) opt[++tail]=fa[i];
        }
    }
    int ans=;
    for (int i=;i<=cnt;i++) if (isbar[i]) ans=max(ans,f[i]);
    printf("%d\n",ans);
}
int main(){
    scanf("%d%d",&n,&m);
    e=;
    for (int i=;i<=m;i++){
        scanf("%d%d",&x[i],&y[i]);
        add(x[i],y[i]);
    }
    for (int i=;i<=n;i++) scanf("%d",&w[i]);
    scanf("%d%d",&s,&p);
    memset(isp,false,sizeof(isp));
    for (int i=;i<=p;i++){
        int tmp;
        scanf("%d",&tmp);
        isp[tmp]=true;
    }
    time=;top=;
    memset(vis,true,sizeof(vis));
    memset(ins,false,sizeof(ins));
    memset(isbar,false,sizeof(isbar));
    for (int i=;i<=n;i++) if (vis[i]) tarjan(i);
    memset(link,,sizeof(link));
    memset(next,,sizeof(next));
    e=;
    for (int i=;i<=m;i++) if (pos[x[i]]!=pos[y[i]]) add(pos[x[i]],pos[y[i]]);
    memset(vis,true,sizeof(vis));
    dfs(pos[s]);
    solve(pos[s]);
    return ;
}

  


 

[BZOJ1177][BZOJ1178][BZOJ1179]APIO2009解题报告的更多相关文章

  1. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  2. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  3. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  4. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  5. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  6. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  7. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  8. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  9. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

随机推荐

  1. Ubuntu使用时遇到的问题

    启动时显示System program problem detected 解决办法: 打开命令行窗口:Ctrl+Alt+T 执行命令:sudo gedit /etc/default/apport 把e ...

  2. KeyPress 和KeyDown 、KeyPress之间的区别

    虽然从字面理解, KeyDown是按下一个键的意思, 但实际上二者的根本区别是, 系统由KeyDown返回键盘的代码, 然后由TranslateMessage函数翻译成成字符, 由KeyPress返回 ...

  3. VBA练习-复杂一点

    '日期添加 Sub addDate(d) Dim rg As Range, dd As Date d = Split(d, ) d = Replace(d, ".", " ...

  4. 【EF】解决EF批量操作,Z.EntityFramework.Extensions 过期方案

    方案一: 使用EntityFramework.Extended优点: 启下载量是Z.EntityFramework.Extensions的10倍+ 不会过期缺点:不能批量Insert 方案二:解决批量 ...

  5. echart模块化单文件引入

    echart模块化单文件引入百度上面是推荐这样使用.今天看了一下,做了个Demo. 文件结构如下:

  6. BZOJ5322:[JXOI2018]排序问题——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5322 https://loj.ac/problem/2543 <-可以看数据,要没有这数据我 ...

  7. BZOJ3932:[CQOI2015]任务查询系统——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3932 题面源于洛谷 题目描述 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成 ...

  8. UVA.11464 Even Parity (思维题 开关问题)

    UVA.11464 Even Parity (思维题 开关问题) 题目大意 给出一个n*n的01方格,现在要求将其中的一些0转换为1,使得每个方格的上下左右格子的数字和为偶数(如果存在的话),求使得最 ...

  9. react事件机制

    1. react的事件是合成事件((Synethic event),不是原生事件 <button onClick={this.handleClick}></button> &l ...

  10. bzoj1211: [HNOI2004]树的计数(purfer编码)

    BZOJ1005的弱化版,不想写高精度就可以写这题嘿嘿嘿 purfer编码如何生成?每次将字典序最小的叶子节点删去并将其相连的点加入序列中,直到树上剩下两个节点,所以一棵有n个节点的树purfer编码 ...