Codeforces Round #225 (Div. 2)(B思维题,E:dfs+树状数组)

来源:互联网 发布:维奈斯淘客采集软件 编辑:程序博客网 时间:2024/05/22 08:18

A. Coder

题意:在一张网格上放置棋子,他能攻击到上下左右的地方,问最多放多少棋子,使其不能相互攻击到,输出一种方法;

思路:从第一个开始放,标记其上下左右。

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int maxn=1005;char grid[maxn][maxn];bool vis[maxn][maxn];int n,ans;void init(){    ans=1;    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)        {            grid[i][j]='.';            vis[i][j]=false;        }}int main(){    cin>>n;    init();    grid[1][1]='C';    vis[1][1]=vis[1][2]=vis[2][1]=1;    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)            if(!vis[i][j])            {                grid[i][j]='C';                ans++;                vis[i][j]=vis[i+1][j]=vis[i-1][j]=vis[i][j-1]=vis[i][j+1]=1;            }    }    cout<<ans<<endl;    for(int i=1;i<=n;i++)        cout<<grid[i]+1<<endl;    return 0;}

B. Multitasking

思路:直接模拟,刚开始算错复杂度了,应该是m^2*n,想成n^2*m了,按步骤最多的写就可以了,后来看了别人的代码,瞬间感觉弱爆了,直接输出就可以。。。

#include <map>#include <cmath>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 102;int g[maxn][maxn];int r[maxn];struct node{    int ll, rr;}q[maxn * maxn];int main(){    int n, m, k;    while (scanf("%d %d %d",&n,&m,&k)!=EOF){        int a, b;        for (int i=0; i<n; i++){            for (int j=0; j<m; j++){                scanf("%d",&r[j]);            }            for (int j=0; j<m; j++){                for (int l=j+1; l<m; l++){                    if (k == 0 && r[j] > r[l]){                        g[j][l] = 1;                    }                    if (k == 1 && r[j] < r[l]){                        g[l][j] = 1;                    }                }            }        }        int tp = 0;        for (int i=0; i<m; i++){            for (int j=0; j<m; j++){                if (g[i][j]){                    q[tp].ll = i;                    q[tp++].rr = j;                }            }        }        printf("%d\n",tp);        for (int i=0; i<tp; i++){            printf("%d %d\n",q[i].ll+1,q[i].rr+1);        }    }    return 0;}

#include <cstdio>using namespace std;int main(){int n,m,k;scanf("%d%d%d",&n,&m,&k);printf("%d\n",(m*m-m)/2);for(int i=1;i<=m;i++)for(int j=i+1;j<=m;j++)if(k==0)printf("%d %d\n",i,j);elseprintf("%d %d\n",j,i);return 0;}

C. Milking cows

思路:只需要计算每头朝左的牛右边所有朝右的牛的个数,然后求和就可以。或者反过来算也行。

#include<iostream>using namespace std;typedef long long LL;LL n,ans,sum;int main(){    cin>>n;    ans=sum=0;    int k;    for(int i=0;i<n;i++)    {        cin>>k;        if(k==1)        sum++;        else ans+=sum;    }    cout<<ans<<endl;    return 0;}

E. Propagating tree(参考)

题意:有一颗n个结点的有根树,每个结点有一个值a[i],可以对树进行以下两种操作:

1、"1 x val" 把结点x的值加val,同时把结点x的儿子的值加上-val,结点x的儿子的儿子加上val,等等依次这样进行

2、"2 x"查询结点x的值

思路:由于第一个操作是对整个以x为根的子树进行修改,因此我们可以利用dfs序把整个子树重新编号为连续的区间,然后与结点x的树高的奇偶性相同的儿子结点是加val,否则就是加-val,一般我们我们遇到的区间操作都是,对某个区间进行同一种修改操作,但是此题是结点的奇偶性不同,操作不同,如果我们用一颗线段树或者树状数组的话搞起来很麻烦,我们可以根据结点的奇偶搞两颗BIT,然后根据结点x的奇偶性对对应的BIT进行相应的区间修改操作,查询也是根据结点的奇偶性在对应的BIT上进行查询

下面是代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn=200100;struct node{    int v,next;}edge[2*maxn];int n,m,step=0,num=1;int deg[maxn],high[maxn],tree[2][maxn],vis[maxn],low[maxn],a[maxn],head[maxn];void add_edge(int u,int v){    edge[num].v=v;    edge[num].next=head[u];    head[u]=num++;}void dfs(int u,int flag){    low[u]=++step;//记录到达当前节点的时间    deg[u]=flag;//标记当前节点的奇偶性    vis[u]=1;    for(int i=head[u];i!=-1;i=edge[i].next)    {        if(!vis[edge[i].v])            dfs(edge[i].v,(flag+1)%2);    }    high[u]=step;//记录当前节点能管辖的范围}void add(int x,int val,int flag){    while(x<=n)    {        tree[flag][x]+=val;        x+=x&(-x);    }}int sum(int x,int flag){    int ans=0;    while(x>0)    {        ans+=tree[flag][x];        x-=x&(-x);    }    return ans;}int main(){    //freopen("in.txt","r",stdin);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    memset(head,-1,sizeof(head));    for(int i=1;i<n;i++)    {        int u,v;        scanf("%d%d",&u,&v);        add_edge(u,v);    }    memset(vis,0,sizeof(vis));    memset(tree,0,sizeof(tree));    dfs(1,0);    int op,x,val;    for(int i=0;i<m;i++)    {        scanf("%d%d",&op,&x);        if(op==1)        {            scanf("%d",&val);            add(low[x],val,deg[x]);            add(high[x]+1,-val,deg[x]);            add(low[x],-val,(deg[x]+1)%2);            add(high[x]+1,val,(deg[x]+1)%2);        }        else cout<<a[x]+sum(low[x],deg[x])<<endl;    }    return 0;}


0 0