Codeforces Round #207 (Div. 2) C - Knight Tournament

来源:互联网 发布:淘宝专柜小样是真的吗 编辑:程序博客网 时间:2024/05/18 00:51

这题有三种做法,通常做法是线段树,当你熟悉STL可以用set做,但有更牛的优化做法,在空间上完虐前两种。

题意:输入n和m,代表n个骑士和m场对决,每个骑士的编号从1~n,每个对决会给出l,r,x表示从l到r这区间的所有人参加这场对决,胜者为x,输的人输出第一次败给哪个骑士编号,最后只有一个胜者胜者输出0.

思路:正如之前所说,直接用线段树更新区间,然后询问即可。

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long LL;#define INF 0x3f3f3f3fstruct Node{  int l,r,value;}tree[1200005];void bulid(int v,int l,int r){  tree[v].l=l;  tree[v].r=r;  if(l==r)  {    tree[v].value=0;    return;  }  int mid=(l+r)/2;  bulid(v*2,l,mid);  bulid(v*2+1,mid+1,r);  tree[v].value=tree[v*2].value+tree[v*2+1].value;}void update(int v,int l,int r,int m){  if(tree[v].l==l&&tree[v].r==r)  {    if(tree[v].value==0)      tree[v].value=m;    return;  }  if(tree[v].value) return;  int mid=(tree[v].l+tree[v].r)/2;  if(r<=mid)    update(v*2,l,r,m);  else  {    if(l>mid)      update(v*2+1,l,r,m);    else    {      update(v*2,l,mid,m);      update(v*2+1,mid+1,r,m);    }  }}int ans;void query(int v,int m){  if(tree[v].value) ans=tree[v].value;  if(tree[v].l==m&&tree[v].r==m) return;  int mid=(tree[v].l+tree[v].r)/2;  if(m<=mid) query(v*2,m);  else query(v*2+1,m);}int L[300005],R[300005],X[300005];int main(){  int n,m,l,r,x;  while(~scanf("%d%d",&n,&m))  {    bulid(1,1,n);    for(int i=0;i<m;i++)      scanf("%d%d%d",&L[i],&R[i],&X[i]);    for(int i=0;i<m;i++)    {      int a,b;      a=L[i],b=X[i]-1;      if(b>=a)      {        update(1,a,b,X[i]);      }      a=X[i]+1;b=R[i];      if(a<=b)      {        update(1,a,b,X[i]);      }    }    for(int i=1;i<n;i++)    {      ans=0;query(1,i);      printf("%d ",ans);    }    ans=0;query(1,n);    printf("%d\n",ans);  }}
STL采用set容器每次对决输入用earse函数删除区间【l,r】再把x用insert插入回去。

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long LL;#define INF 0x3f3f3f3fset<int>s;int a[300005];int main(){  int n,m,x,y,z;  scanf("%d%d",&n,&m);  for(int i=1;i<=n;i++)    s.insert(i);  set<int>::iterator l,r,it;  memset(a,0,sizeof(a));  for(int i=0;i<m;i++)  {    scanf("%d%d%d",&x,&y,&z);    l=s.lower_bound(x);    r=s.upper_bound(y);    for(it=l;it!=r;it++)    {      if(*it!=z)        a[*it]=z;    }    s.erase(l,r);s.insert(z);  }  for(int i=1;i<=n;i++)  {    printf("%d ",a[i]);  }  printf("\n");}
借鉴别人的优化做法,就是有点难想,理解起来需要花点时间

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long LL;#define INF 0x3f3f3f3fint ans[300005],p[300005];int getl(int x){  int i=x,j;  while(x!=p[x])    x=p[x];  while(i!=p[i])  {    j=p[i];    p[i]=x;    i=j;  }  return x;}int main(){  int n,m,l,r,x;  scanf("%d%d",&n,&m);  for(int i=1;i<=n+1;i++) p[i]=i;  for(int i=0;i<m;i++)  {    scanf("%d%d%d",&l,&r,&x);    int j=getl(l);    while(j<=r)    {      if(j!=x)      {        ans[j]=x;p[j]=j+1;      }      j++;      j=getl(j);    }  }  for(int i=1;i<n;i++)  {    printf("%d ",ans[i]);  }  printf("%d\n",ans[n]);}




1 0
原创粉丝点击