Codeforces上几道神一般的数据结构题

      • Codeforces 620E New Year Tree
      • Codeforces 121E Lucky Array
      • Codeforces 633H Fibonacci-ish II
    • 我来安利一道题.

Codeforces 620E New Year Tree

给一棵树,每个点有个颜色,支持对子树进行覆盖,询问子树中含有多少种不同颜色.颜色最多60种.
如果没有修改操作,可以使用莫队,但是这里有修改操作,不能使用莫队.
那么还剩下颜色最多60种这个突破口.
由于相同的颜色只计算一次,自然地想到用一个二进制整数存储有多少种颜色,询问时直接用 or o r 运算计算,求出算出的数中 1 1 的个数就可以了.
因为只有子树操作,不需要树链剖分.
还有一点要注意的,计算的时候要用1ll< 这里我手写了.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  re0 x=0,f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
inline void read(rel &x){
  x=0;re0 f=1;rec c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  x=f?x:-x;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  re0 bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
inline char fuhao(){
  rec c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=4e5;
typedef int fuko[yuzu|10];
vector<int> lj[yuzu|10];
int n,m,cnt;
fuko dfn,edf,ord,a;

void dfs(int u,int fa){
dfn[u]=++cnt,ord[cnt]=u;
for (int v:lj[u]) if (v^fa) dfs(v,u);
edf[u]=cnt;
}

typedef ll karen[yuzu<<2|13];
struct segtree{
#define le rt<<1
#define ri le|1
#define ls le,l,mid
#define rs ri,mid+1,r
karen val,lazy;
void build(int rt=1,int l=1,int r=n){
  lazy[rt]=-1;
  if (l==r) val[rt]=1ll<else{
    int mid=l+r>>1;
    build(ls),build(rs);
    val[rt]=val[le]|val[ri];
    }
  }
void push_down(int rt){
  if (~lazy[rt]){
    lazy[le]=lazy[ri]=lazy[rt];
    val[le]=val[ri]=1ll<1;
    }
  }
void update(int ql,int qr,int v,int rt=1,int l=1,int r=n){
  if (ql>r||qrreturn;
  if (ql<=l&&qr>=r){
    val[rt]=1ll<1;
    lazy[rt]=v-1;
    }else{
    int mid=l+r>>1;
    push_down(rt);
    update(ql,qr,v,ls),update(ql,qr,v,rs);
    val[rt]=val[le]|val[ri];
    }
  }
ll query(int ql,int qr,int rt=1,int l=1,int r=n){
  if (ql>r||qrreturn 0;
  if (ql<=l&&qr>=r) return val[rt];
  int mid=l+r>>1;
  push_down(rt);
  return query(ql,qr,ls)|query(ql,qr,rs);
  }
}my_;

#define all(u) dfn[u],edf[u]
int _bp(ll x){
int ans=0;
for (;x;x&=x-1) ++ans;
return ans;
}

int main(){
re0 i;
n=read(),m=read();
for (i=1;i<=n;++i) a[i]=read()-1;
for (i=1;iint u=read(),v=read();
  lj[u].push_back(v);
  lj[v].push_back(u);
  }
dfs(1,0),my_.build();
for (;m--;){
  int op=read(),u=read();
  if (op==1){ 
    my_.update(all(u),read());
    }
  else{
    write(_bp(my_.query(all(u)))),pl;
    }
  }
}

Codeforces 121E Lucky Array

定义幸运数字为只含有4和7的数字,给出一个序列,支持区间加,求区间内有多少个幸运数字.
这题一想好像不能使用线段树或者树状数组,否则一定会退化成单点修改.
我尝试用暴力卡常去跑,在第62个点T了,我怎么都救不了.
那咱们没有办法了,就真的用树状数组单点修改去信仰了.
结果过了.div1.E还有这样的题,真的是一道神题啊.
所有数不超过 10000 10000 ,我们先用 dfs d f s 求出所有幸运数字,放在一个数组里,可以 O(1) O ( 1 ) 判断一个数是不是幸运数字.接下来用树状数组瞎跑就可以过了.

/*当然不加卡常头文件,不用float也是可以过的.*/
#pragma GCC optimize("Ofast,no-stack-protector,Ofast")
#pragma GCC target("avx,sse2")
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
inline void read(rel &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  x=f?x:-x;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  re0 bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
inline char fuhao(){
  rec c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=1e5;
int n=read(),m=read();
typedef int fuko[yuzu|10];
fuko lnum,a;

void dfs(int k,int num){
if (!k) return;
lnum[num]=1;
dfs(k-1,num*10+4);
dfs(k-1,num*10+7);
}

struct _bit{
fuko c;
#define lowbit(x) (x&-x)
void add(int x,int k){for (;x<=n;x+=lowbit(x)) c[x]+=k;}
int query(int x){int s=0;for (;x;x-=lowbit(x)) s+=c[x];return s;}
}my_;

int main(){
re0 i;
dfs(5,0);
for (i=1;i<=n;++i){
  if (lnum[a[i]=read()]) my_.add(i,1);
  }
for (;m--;){
  char op=fuhao();
  float l=read(),r=read();
  if (op=='a'){
    float k;
    scanf("%f",&k);
    for (i=l;i<=r;++i){
      if (lnum[a[i]]) my_.add(i,-1);
      if (lnum[a[i]+=k]) my_.add(i,1);
      }
    }else{
    write(my_.query(r)-my_.query(l-1)),pl;
    }
  }
}

Codeforces 633H Fibonacci-ish II

q个询问,每次询问[l,r]区间排序去重后F(a[l to r])%m 的值.
F(x)指第x个斐波那契数.

标算是线段树维护莫队,O(n*logn*sqrt(n)),常数非常大.
因此用O(n^2)暴力爆过去,个别常数较大的标算有时不一定能够跑得比暴力快.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
#define yi first
#define er second
typedef pair<int,int> pii;
const int yuzu=3e4;
typedef int fuko[yuzu|10];
fuko ans,step,fib={1,1},l,r,last;
int n=read(),m=read();
pii a[yuzu|10];

int main(){
int i,j;
for (i=1;i<=n;++i) a[i]=pii(read(),i);
sort(a+1,a+n+1);
memset(last,-1,sizeof last);
for (i=2;i<=n;++i) fib[i]=(fib[i-1]+fib[i-2])%m;
int q=read();
for (i=1;i<=q;++i) l[i]=read(),r[i]=read();
for (i=1;i<=n;++i){
  int d=a[i].yi%m;
  for (j=1;j<=q;++j){
    if (a[i].er>=l[j]&&a[i].er<=r[j]&&a[i].yi^last[j]){
      ans[j]=(ans[j]+fib[step[j]++]*d)%m;
      last[j]=a[i].yi;
      }  
    }
  }
for (i=1;i<=q;++i) write(ans[i]),pl;
}

谢谢大家.

我来安利一道题.

这题是Codeforces620E的升级版,需要树链剖分来解决.
洛谷 U24602 沙耶之歌(沙耶の唄)

你可能感兴趣的:(codeforces,数据结构)