zoukankan      html  css  js  c++  java
  • CSP非专业S 2020总结 暨 NOIP2020准备日记


    CSP-S 2020总结

    我实力确实很不够。


    NOIP2020准备日记

    前言

    距离 NOIP2020 还有 20+ 天。

    我的实力还是不够, 从今天开始吧。

    2020.11.8 14:09

    2020.11.8

    啊,由于直到上午都是假期,今天的训练从下午开始。

    补了一场膜你的题。 17:03

    T1

    脑糊一下发现字符的贡献是独立的, 分别考虑每个字符,发现每个字符只可能是 s 中出现次数最多的字符之一。

    T2

    排序不等式, 注意支持负数。

    T3

    分类讨论, 不好。

    枚举大法, 好。

    T4

    暂时不补。


    开车旅行这道题, 以前没做出来主要是细节没写好, 这题其实不难写, 用链表写也才100多行。比较关键的地方不少,被 (x_0) 部分的答案更新卡掉了不少时间, 没有考虑到这个答案更新的逻辑居然不是那么简洁。

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    
    const int N = 1e5+3, inf=2000000000;
    
    int n, h[N], fi[N], se[N];
    int to[18][N];
    LL sa[18][N], sb[18][N];
    
    int a[N];
      bool cmp(int x,int y) {return h[x]<h[y]; }
    int pr[N], nt[N];
    void gen(int &fas, int &sas, int o, int t)
    {
      if(fas==0 || abs(t-h[o])<abs(t-h[fas]) || (abs(t-h[o])==abs(t-h[fas]) && h[o]<h[fas])) sas=fas, fas=o;
      else if(sas==0 || abs(t-h[o])<abs(t-h[sas]) || (abs(t-h[o])==abs(t-h[sas]) && h[o]<h[sas])) sas=o;
    }
    int dis(int x,int y)
    { return (x&&y) ? abs(h[x]-h[y]) :0;  }
    void prework()
    {
      for(int i=1;i<=n;++i) a[i]=i;
      sort(a+1,a+1+n,cmp);
      for(int i=2;i<=n;++i) pr[a[i]]=a[i-1], nt[a[i-1]]=a[i];
      for(int i=1;i<n;++i)
      {
        int fas=0, sas=0, o;
        if(o=pr[i]) gen(fas,sas,o,h[i]);
        if(o=pr[pr[i]]) gen(fas,sas,o,h[i]);
        if(o=nt[i]) gen(fas,sas,o,h[i]);
        if(o=nt[nt[i]]) gen(fas,sas,o,h[i]);
        fi[i]=fas, se[i]=sas;
        if(pr[i]) nt[pr[i]] = nt[i];
        if(nt[i]) pr[nt[i]] = pr[i];
      }
      
      for(int i=1;i<=n;++i)
      {
        to[0][i] = se[i];
        to[1][i] = fi[se[i]];
        sa[0][i] = sa[1][i] = dis(i,se[i]);
        sb[1][i] = dis(se[i],fi[se[i]]);
      }
      for(int k=2;k<=17;++k)
        for(int i=1;i<=n;++i)
        {
          to[k][i] = to[k-1][to[k-1][i]];
          sa[k][i] = sa[k-1][i] + sa[k-1][to[k-1][i]];
          sb[k][i] = sb[k-1][i] + sb[k-1][to[k-1][i]];
        }
    }
    
    LL A,B;
    void calc(int s,int x)
    {
    //  cout << "# "<<s<<','<<x<<" : ";
      A = B = 0ll;
      for(int k=17;k>=0;--k)
      {
    //    cout << k << ' ' << s << ' '  << sa[k][s]+sb[k][s] << ' ' << A+B << '
    ';
        if(to[k][s] && (A+B+sa[k][s]+sb[k][s]<=x))
        {
          A += sa[k][s], B += sb[k][s];
          s = to[k][s];
        }
      }
    }
    /*
    4 
    2 3 1 4 
    3 
    4 
    1 3 
    2 3 
    3 3 
    4 3
    */
    int main()
    {
      scanf("%d",&n);
      h[0] = -2000000000;
      for(int i=1;i<=n;++i) scanf("%d",&h[i]);
      prework();
    //  cout<<sb[0][2]<<'
    ';
    //   for(int i=1;i<=n;++i) {
    //     cout << fi[i] << ' ' << se[i] << '
    ';
    //     // for(int k=0;k<=2;++k) cout<<to[k][i]<<' ';
    //   }
      int x0;
      scanf("%d", &x0);
      calc(1,x0);
      LL fz=A, fm=B;
      int as=1;
      for(int i=2;i<=n;++i)
      {
        calc(i,x0);
        // cout << A << ' ' << B << " # "<<fz<<' '<<fm<<' ';
        if(!fm)
        {
          if(!B && h[i]>h[as]) fz=A, fm=B, as=i;
          else if(B) fz=A, fm=B, as=i;
        }
        else
        {
          if(!B) continue;
          if(1ll*A*fm < 1ll*fz*B || (1ll*A*fm==1ll*fz*B && h[i]>h[as])) fz=A, fm=B, as=i;
        }
        // cout<<fz<<' '<<fm<<'
    ';
      }
      cout << as << '
    ';
      int m;
      scanf("%d",&m);
      for(int i=1;i<=m;++i)
      {
        int s,x;
        scanf("%d%d",&s,&x);
        calc(s,x);
        cout << A << ' ' << B << '
    ';
      }
      return 0;
    }
    

    chibi之zhan这道题

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    
    const int N = 1003, mo = 1e9+7;
    int n, m, l, a[N], b[N];
    int f[N][N];
    int t[N];
    inline int lowb(int x) {return x&(-x);  }
    void add(int x, LL v) {for(;x<=n+1;x+=lowb(x)) t[x]=(t[x]+v)%mo;  }
    int ask(int x) {int res=0; for(;x;x-=lowb(x)) res=(res+t[x])%mo;  return res;  }
    
    int main()
    {
      int T;
      scanf("%d", &T);
      for(int id=1;id<=T;++id)
      {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]), b[i]=a[i];
        sort(b+1,b+1+n);
        for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+n+1,a[i])-b+1;
        a[0]=1;
        // discrete
        for(int i=1;i<=n;++i) f[i][1]=1ll;
        for(int j=2;j<=m;++j)
        {
          memset(t,0,sizeof t);
          for(int i=1;i<=n;++i)
          {
            f[i][j] = ask(a[i]-1);
            add(a[i],f[i][j-1]);
          }
        }
        int ans = 0;
        for(int i=m;i<=n;++i) ans = (ans+f[i][m])%mo;
        printf("Case #%d: %d
    ", id, ans);
      }
      return 0;
    }
    

    今天就写几道简单题放松下身心了, 明天开始要开始认真写题了。(我有一个梦想,那就是一天写10道题) 22:08


    2020.11.9

    今天写下搜索。

    写下简单题熟悉下流程

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,w,c[21];
    int hw[21];
    int ans;
    void dfs(int cur, int cnt)
    {
      if(cnt>=ans) return;
      if(cur==n+1)
      {
        ans = min(ans,cnt);
        return;
      }
      hw[++cnt]=c[cur];
      dfs(cur+1,cnt);
      --cnt;
      for(int i=1;i<=cnt;++i)
      {
        if(hw[i]+c[cur]>w) continue;
        hw[i]+=c[cur];
        dfs(cur+1,cnt);
        hw[i]-=c[cur];
      }
    }
    
    bool cmp(int x,int y) {return x>y; }
    int main()
    {
      scanf("%d%d",&n,&w);
      for(int i=1;i<=n;++i) scanf("%d",&c[i]);
      sort(c+1,c+1+n,cmp);
      ans = n+1;
      dfs(1,1);
      cout << ans;
      return 0;
    }
    

    简单题 ims 2

    #include<bits/stdc++.h>
    using namespace std;
    
    char s[82];
    int sum, cnt[1<<9], lg[1<<9];
    int h[82], l[82], b[82];
    int hs[10], ls[10], bs[10];
    
    int lowb(int x) {return x&(-x); }
    
    int dfs(int now)
    {
      if(now==82) return 1;
      int mx=0, as=10;
      for(int i=1,nas;i<=81;++i)
        if(s[i]=='.' && (nas=cnt[ (hs[h[i]]|ls[l[i]]|bs[b[i]])^((1<<9)-1) ])<as) as=nas, mx=i;
      int S = (hs[h[mx]]|ls[l[mx]]|bs[b[mx]])^((1<<9)-1);
      while(S)
      {
        int i = lg[lowb(S)];
        s[mx] = '0'+i+1;
        hs[h[mx]] |= (1<<i);
        ls[l[mx]] |= (1<<i);
        bs[b[mx]] |= (1<<i);
        if(dfs(now+1)) return 1;
        s[mx] = '.';
        hs[h[mx]] ^= (1<<i);
        ls[l[mx]] ^= (1<<i);
        bs[b[mx]] ^= (1<<i);
        S -= lowb(S);
      }
      return 0;
    }
    
    void init()
    {
      lg[0]=-1;
      for(int i=1;i<(1<<9);++i) 
        cnt[i]=cnt[i>>1]+(i&1),
         lg[i]=lg[i>>1]+1;
      for(int i=1;i<=81;++i)
      {
        h[i] = (i-1)/9+1;
        l[i] = (i-1)%9+1;
        b[i] = (i-1)/27*3 + (l[i]-1)/3 + 1;
        // cout << h[i] << ' ' << l[i] << ' ' << b[i] << '
    ';
      }
    }
    
    int main()
    {
      init();
      
      while(scanf("%s",s+1)==1)
      {
        if(s[1]=='e') break;
        memset(hs,0,sizeof hs);
        memset(ls,0,sizeof ls);
        memset(bs,0,sizeof bs);
        sum = 0;
        for(int i=1;i<=81;++i) if(s[i]!='.') {
          ++sum;
          int v = s[i]-'1';
          hs[h[i]] |= (1<<v);
          ls[l[i]] |= (1<<v);
          bs[b[i]] |= (1<<v);
        }
        if(dfs(sum+1))
        {
          printf("%s
    ",s+1);
        }
      }
      return 0;
    }
    

    拼木棒, 也算简单题吧。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n, a[71], sum, mx;
    int len, nd;
    
    int vis[71];
    bool dfs(int now, int l, int las)
    {
      if(now==nd+1) return true;
      if(l==len) return dfs(now+1,0,1);
        int lfail = 0;
      for(int i=las;i<=n;++i)
        if(!vis[i] && l+a[i]<=len && a[i]!=lfail)
        {
          vis[i]=1;
          if(dfs(now,l+a[i],i+1)) return true;
          vis[i]=0;
          lfail = a[i];
          if(l+a[i]==len || l==0) return false;
        }
      return false;
    }
    
    bool cmp(int x,int y) {return x>y;}
    int main()
    {
      while(scanf("%d",&n)==1 && n)
      {
        sum=0, mx=0;
        for(int i=1;i<=n;++i) scanf("%d",&a[i]), sum+=a[i], mx=max(mx,a[i]);
        sort(a+1,a+1+n,cmp);
        for(len=mx; len<=sum; ++len)
          if(sum%len == 0)
          {
            memset(vis,0,sizeof vis);
            nd = sum/len;
            if(dfs(1,0,1)) break;
          }
        cout << min(sum,len) << '
    ';
      }
      return 0;
    }
    

    生日蛋糕, 挺锻炼毛估估的手段。

    // sum pi R^2 H = N pi  --> sum R^2 H = N
    // let dixiadedongxi sum 2 R H smallest
    #include<bits/stdc++.h>
    using namespace std;
    const int M = 21;
    
    int n,m;
    int ans=1000000000;
    int fs[M], fq[M];
    
    //S是体积, Q是面积
    void dfs(int now, int S, int Q, int pR, int pH)
    {
      if(now==m+1)
      {
        if(S==n) ans=min(ans, Q);
        return;
      }
      if(S+fs[now]>n || Q+fq[now]>=ans) return;
      if(S+(m-now+1)*pH*pR*pH<n) return;
      for(int R=pR-1;R>=m-now+1;--R)
        for(int H=pH-1;H>=m-now+1;--H)
        if(S+R*R*H<=n)
        {
          dfs(now+1, S+R*R*H, Q+2*R*H+(now==1?R*R:0), R, H);
        }
    }
    
    int main()
    {
      cin>>n>>m;
      for(int i=m;i>=1;--i)
        fs[i]=(m-i+1)*(m-i+1)*(m-i+1), fq[i]=2*(m-i+1)*(m-i+1);
      fq[1] += m*m*m;
      dfs(1,0,0,sqrt(n),sqrt(n));
      cout << (ans==1000000000?0:ans);
      return 0;
    }
    

    迭代加深练习

    简单的思想。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 101;
    
    int n,m,a[N];
    
    bool v[N];
    bool dfs(int now)
    {
      if(now > m) return a[m]==n;
      int vis[N] = {0};
      for(int i=1;i<=now-1;++i)
        for(int j=1;j<=now-1;++j)
          if(!vis[a[i]+a[j]] && a[i]+a[j]>a[now-1])
          {
            vis[a[i]+a[j]]=1;
            a[now] = a[i]+a[j];
            if(dfs(now+1)) return true;
          }
      return false;
    }
    
    int main()
    {
      a[1]=1;
      while(scanf("%d",&n)==1 && n)
      {
        if(n==1)
        {
          puts("1");
          continue;
        }
        for(m=2; m<=n; ++m)
          if(dfs(2)) break;
        for(int i=1;i<=m;++i) cout << a[i] << ' ';
        cout << '
    ';
      }
      return 0;
    }
    

    meet in the middle 练习

    巧妙的思想。

    懒了,算了。

    ”手写“堆

    直接用 make_heap 及相关函数, 听人说这些函数和 priority_queue 内部用的是同一套算法, 但是由于 priority_queue 用的是 vector 作容器, 所以看上去就很慢;同时由于这类函数可以用于自定义的数组, 所以可扩展性稍微有点高。

    跑最短路的话堆的大小只需要开 N+M 就行。

    开了 O2 跑最短路两者效率差不多。

    在不开 O2 的情况下比较一下效率:

    //make_heap 比 priority_queue 快了大于 500ms
    //849ms
    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=100003, M=200003;
    
    int n,m,s;
    int ct, hd[N], nt[M+1], vr[M+1], w[M+1];
    void ad(int u,int v,int W) {nt[++ct]=hd[u], hd[u]=ct; vr[ct]=v, w[ct]=W;}
    
    struct node{
    	int id, d;
    };
    bool operator<(node x,node y)
    {
    	return !(x.d<y.d);
    }
    
    int d[N], v[N];
    priority_queue<node>q;
    void Dij()
    {
    	for(int i=1;i<=n;++i) d[i]=2e9;
    	d[s]=0;
    	q.push((node){s,0});
    	while(!q.empty())
    	{
    		int x=q.top().id; q.pop();
    		if(v[x]) continue;
    		v[x]=1;
    		for(int i=hd[x];i;i=nt[i])
    		{
    			int y=vr[i], z=w[i];
    			if(d[y] > d[x]+z)
    			{
    				d[y] = d[x]+z;
    				q.push((node){y,d[y]});
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i=0;i<m;++i)
    	{
    		int u,v,W;
    		scanf("%d%d%d",&u,&v,&W);
    		ad(u,v,W);
    	}
    	Dij();
    	for(int i=1;i<=n;++i) cout << d[i] << ' ';
    	return 0;
    }
    
    
    //373 ms
    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=100003, M=200003;
    
    int n,m,s;
    int ct, hd[N], nt[M+1], vr[M+1], w[M+1];
    void ad(int u,int v,int W) {nt[++ct]=hd[u], hd[u]=ct; vr[ct]=v, w[ct]=W;}
    
    struct node{
    	int id, d;
    };
    bool operator<(node x,node y)
    {
    	return !(x.d<y.d);
    }
    
    int d[N], v[N];
    node q[N*5];
    int tot;
    void Dij()
    {
    	for(int i=1;i<=n;++i) d[i]=2e9;
    	d[s]=0;
    	q[++tot] = (node){s,0};
    	while(tot)
    	{
    		int x=q[1].id;
    		pop_heap(q+1,q+1+tot--);
    		if(v[x]) continue;
    		v[x]=1;
    		for(int i=hd[x];i;i=nt[i])
    		{
    			int y=vr[i], z=w[i];
    			if(d[y] > d[x]+z)
    			{
    				d[y] = d[x]+z;
    				q[++tot] = (node){y,d[y]};
    				push_heap(q+1,q+1+tot);
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i=0;i<m;++i)
    	{
    		int u,v,W;
    		scanf("%d%d%d",&u,&v,&W);
    		ad(u,v,W);
    	}
    	Dij();
    	for(int i=1;i<=n;++i) cout << d[i] << ' ';
    	return 0;
    }
    

    一道简单题,一开始算法假了改了半天。

    // 二分 + 0/1 bfs
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1003, M=10003;
    
    int n,p,k;
    int ct, hd[N], nt[M*2+1], vr[M*2+1], w[M*2+1];
    void ad(int u,int v,int W) {nt[++ct]=hd[u], hd[u]=ct; vr[ct]=v, w[ct]=W; }
    
    int d[N];
    deque<int>q;
    bool chk(int lim)
    {
      for(int i=2;i<=n;++i) d[i]=21474836;
      d[1]=0;
      q.push_back(1);
      
      while(!q.empty())
      {
        int x=q.front(); q.pop_front();
        for(int i=hd[x];i;i=nt[i])
        {
          int y=vr[i], z=(w[i]>lim);
          if(d[y]>d[x]+z)
          {
            d[y]=d[x]+z;
            if(z) q.push_back(y);
            else q.push_front(y);
          }
        }
      }
      return d[n]<=k;
    }
    
    int main()
    {
      int l=0,r=0,mx=0;
      scanf("%d%d%d",&n,&p,&k);
      for(int i=0;i<p;++i)
      {
        int u,v,W;
        scanf("%d%d%d",&u,&v,&W);
        ad(u,v,W), ad(v,u,W);
        mx = max(mx,W);
      }
      r=mx+1;
      while(l!=r)
      {
        int mid = (l+r)>>1;
        if(chk(mid)) r=mid;
        else l=mid+1;
      }
      cout << (l==mx+1?-1:l);
      // cout << mx<<'
    ';
      return 0;
    }
    

    无向图联通性

    桥一定是搜索树中的边, 一个简单环中的边一定都不是桥。

    B城, 在搜索树上统计答案

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+3, M=5e5+3;
    
    int n,m;
    int ct, hd[N], nt[M*2+1], vr[M*2+1];
    void ad(int x,int y) {nt[++ct]=hd[x], hd[x]=ct; vr[ct]=y;  }
    
    long long ans[N];
    
    int rt, cnt, dfn[N], low[N], siz[N];
    bool cut[N];
    void tar(int x)
    {
      dfn[x] = low[x] = ++cnt;
      siz[x] = 1;
      int flg=0, sum=0;
      for(int i=hd[x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!dfn[y])
        {
          tar(y);
          siz[x] += siz[y];
          low[x] = min(low[x],low[y]);
          if(low[y]>=dfn[x])
          {
            ++flg;
            if(flg>1 || x!=rt) cut[x]=true;
            
            sum += siz[y];
            ans[x] += 1ll * siz[y] * (n-siz[y]);
          }
        }
        else low[x] = min(low[x],dfn[y]);
        
      if(cut[x])
        ans[x] += 1ll * (n-sum-1) * (sum+1) + (n-1);
      else
        ans[x] = 2ll*(n-1);
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      for(int i=0,a,b; i<m; ++i)
      {
        scanf("%d%d",&a,&b);
        ad(a,b), ad(b,a);
      }
      tar(rt=1);
      for(int i=1;i<=n;++i) cout << ans[i] << '
    ';
      return 0;
    }
    

    简单题,感谢出题人放水

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e5+3, M=2e5+3;
    
    int n,m;
    int ct, hd[2][N], nt[M*4+1], vr[M*4+1];
    void ad(int i,int u,int v) {nt[++ct]=hd[i][u], hd[i][u]=ct; vr[ct]=v; }
    
    int cnt, dfn[N], low[N];
    bool bri[M*2+1];
    void tar(int x,int in_e)
    {
      dfn[x] = low[x] = ++cnt;
      for(int i=hd[0][x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!dfn[y])
        {
          tar(y,i);
          low[x] = min(low[x],low[y]);
          
          if(low[y]>dfn[x]) bri[i]=bri[i^1]=true;
        } else
            if(i != (in_e^1)) low[x]=min(low[x],dfn[y]);
    }
    
    int col[N], ccnt;
    void dfs(int x)
    {
      col[x] = ccnt;
      for(int i=hd[0][x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!col[y] && !bri[i]) dfs(y);
    }
    
    int ans, vis[N];
    
    int dep[N], fa[N];
    void dfs2(int x)
    {
      for(int i=hd[1][x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(y!=fa[x]) dep[y]=dep[x]+1, fa[y]=x, dfs2(y);
    }
    
    int main()
    {
      int id=0;
      while(scanf("%d%d",&n,&m)==2 && n && m)
      {
        printf("Case %d:
    ", ++id);
        ct=1;
        memset(hd,0,sizeof hd);
        memset(dfn,0,sizeof dfn);
        memset(bri,0,sizeof bri);
        ccnt=0;
        memset(col,0,sizeof col);
        for(int i=0,a,b; i<m; ++i)
        {
          scanf("%d%d",&a,&b);
          ad(0,a,b);
          ad(0,b,a);
        }
        tar(1,0);
        for(int i=1;i<=n;++i)
          if(!col[i])
          {
            ++ccnt;
            dfs(i);
          }
        ans = 0;
        int oct=ct;
        for(int i=2;i<=oct;i+=2)
          if(bri[i])
          {
            ++ans;
            ad(1,col[vr[i]],col[vr[i^1]]);
            ad(1,col[vr[i^1]],col[vr[i]]);
          }
        fa[1]=0;
        dfs2(1);
        memset(vis,0,sizeof vis);
        int q;
        scanf("%d",&q);
        while(q--)
        {
          int a,b;
          scanf("%d%d",&a,&b);
          a=col[a], b=col[b];
          if(a==b)
          {
            cout << ans << '
    ';
            continue;
          }
          dep[a]>dep[b] ? a^=b^=a^=b :0;
          while(dep[b]>dep[a]) {
            if(!vis[b]) --ans, vis[b]=1;
            b=fa[b];
          }
          while(a!=b) {
            if(!vis[b]) --ans, vis[b]=1;
            if(!vis[a]) --ans, vis[a]=1;
            b=fa[b], a=fa[a];
          }
          cout << ans << '
    ';
        }
        cout << '
    ';
      }
      return 0;
    }
    

    v-DCC缩点

    void tarjan(int x)
    {
      dfn[x] = low[x] = ++num;
      sta[++top] = x;
      if(x==root && hd[x]==0) { // 孤立点
        dcc[++cnt].push_back(x);
        return;
      }
      int flg=0;
      for(int i=hd[x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!dfn[y])
        {
          tarjan(y);
          low[x] = min(low[x],low[y]);
          if(low[y]>=dfn[x])
          {
            ++flg;
            if(flg>1 || x!=root) cut[x] = true;
            
            ++cnt;
            int z;
            do{
              s = sta[top--];
              dcc[cnt].push_back(z);
            } while(z!=y);
            dcc[cnt].push_back(x);
          }
        }
        else low[x] = min(low[x],dfn[y]);
    }
    

    圆桌骑士,习得了多测的新技能

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 1003, M = 1000003;
    
    int n,m;
    int ct, hd[N], nt[M*2+1], vr[M*2+1];
    void ad(int x,int y) {nt[++ct]=hd[x], hd[x]=ct; vr[ct]=y; }
    
    int rt, cnt, dfn[N], low[N];
    vector<int>dcc[N];
    int dcnt;
    int sta[N], tp;
    
    void tar(int x)
    {
      dfn[x] = low[x] = ++cnt;
      if(rt==x && !hd[x])
      {
        dcc[++dcnt].clear();
        dcc[dcnt].push_back(x);
        return;
      }
      sta[++tp] = x;
      for(int i=hd[x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!dfn[y])
        {
          tar(y);
          low[x] = min(low[x],low[y]);
          
          if(low[y]>=dfn[x])
          {
            dcc[++dcnt].clear();
            int z;
            do{
              z=sta[tp--];
              dcc[dcnt].push_back(z);
            } while(z!=y);
            dcc[dcnt].push_back(x);
          }
        }
        else low[x] = min(low[x],dfn[y]);
    }
    
    bool ok[N], vis[N];
    int col[N];
    
    bool dfs(int x)
    {
      for(int i=hd[x],y=vr[i]; i; i=nt[i],y=vr[i])
      {
        if(!ok[y]) continue;
        if(!col[y]) {
          col[y] = 3-col[x];
          if(!dfs(y)) return false;
        } else if(col[x]==col[y]) return false;
      }
      return true;
    }
    
    bool G[N][N];
    
    int main()
    {
      while(scanf("%d%d",&n,&m)==2 && n && m)
      {
        ct=0;
        memset(hd,0,sizeof hd);
        dcnt=0;
        memset(dfn,0,sizeof dfn);
        cnt=0;
        memset(vis,0,sizeof vis);
        memset(col,0,sizeof col);
        tp=0;
        memset(G,0,sizeof G);
        for(int i=0,a,b; i<m; ++i)
        {
          scanf("%d%d",&a,&b);
          G[a][b] = G[b][a] = true;
        }
        for(int i=1;i<=n;++i)
          for(int j=i+1;j<=n;++j)
            if(!G[i][j]) ad(i,j), ad(j,i);
        for(int i=1;i<=n;++i)
          if(!dfn[i]) tar(rt=i);
        int ans = 0;
        for(int i=1;i<=dcnt;++i)
        {
          vector<int>::iterator it;
          for(it=dcc[i].begin(); it!=dcc[i].end(); ++it)
            ok[*it] = true;
          int x = *dcc[i].begin();
          col[x] = 1;
          if(!dfs(x)) {
            for(it=dcc[i].begin(); it!=dcc[i].end(); ++it)
              vis[*it] = true;
          }
          for(it=dcc[i].begin(); it!=dcc[i].end(); ++it)
            ok[*it] = false, col[*it]=0;
        }
        for(int i=1;i<=n;++i) if(vis[i]) ++ans;
        cout << n-ans << '
    ';
      }
      return 0;
    }
    

    令人印象深刻的错误, 由于考虑不周。

    我吹爆 Kosaraju 算法, 短小又方便。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=103, M=10003;
    
    int n;
    int ct, hd[2][N], nt[M*2+3], vr[M*2+3];
    void ad(int i,int x,int y) {nt[++ct]=hd[i][x], hd[i][x]=ct; vr[ct]=y; }
    
    int sta[N],tp;
    int vis[N], dcc[N], dcnt;
    
    void dfs1(int x)
    {
      vis[x]=1;
      for(int i=hd[0][x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!vis[y]) dfs1(y);
      sta[++tp]=x;
    }
    
    void dfs2(int x)
    {
      dcc[x] = dcnt;
      for(int i=hd[1][x],y=vr[i]; i; i=nt[i],y=vr[i])
        if(!dcc[y]) dfs2(y);
    }
    
    void kosaraju()
    {
      for(int i=1;i<=n;++i)
        if(!vis[i]) dfs1(i);
      for(int i=tp;i>=1;--i)
        if(!dcc[sta[i]]) ++dcnt, dfs2(sta[i]);
    }
    
    int ideg[N], odeg[N];
    
    int main()
    {
      
      scanf("%d",&n);
      for(int x=1;x<=n;++x)
      {
        int y;
        while(scanf("%d",&y)==1 && y) ad(0,x,y), ad(1,y,x);
      }
      kosaraju();
      if(dcnt==1)
      {
        puts("1");
        puts("0");
        return 0;
      }
      for(int x=1;x<=n;++x)
        for(int i=hd[0][x],y=vr[i]; i; i=nt[i],y=vr[i])
          if(dcc[x]!=dcc[y])
            ++odeg[dcc[x]], ++ideg[dcc[y]];
      int i0_=0, o0_=0;
      for(int i=1;i<=dcnt;++i)
        i0_ += ideg[i]==0,
        o0_ += odeg[i]==0;
      cout << i0_ << '
    ' << max(i0_,o0_);
      return 0;
    }
    

    小结

    这两天就是做了点题,复习了点算法,由于都是以前会的算法,所以写起来不慢。
    效率实在太低啦。
    明天开始要做一场膜你赛, 顺便要开始学新算法啦。
    暂定的算法学习是单调队列优化 DP。
    还有时间的话就学一下更精妙的 DP吧。
    今天晚上剩下的时间就复习下数论吧。

    边界令人印象深刻
    反逻辑错误通常出现于过度劳累之后忘了什么

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    
    const int N=1000003, M=70003;
    
    int m, p[M], v[M];
    void euler(int n)
    {
      for(int i=2;i<=n;++i)
      {
        if(!v[i]) p[++m] = v[i] = i;
        for(int j=1;j<=m;++j)
        {
          if(p[j]>n/i || p[j]>v[i]) break;
          v[i*p[j]] = p[j];
        }
      }
    }
    
    int n, vis[N];
    int t;
    LL a[N];
    
    int main()
    {
      euler(70000);
      LL L,R;
      while(scanf("%lld%lld",&L,&R)==2)
      {
        memset(vis,0,sizeof vis);
        for(int i=1;i<=m && p[i]<=R;++i)
          for(int j=max((int)ceil(L/p[i]),2); j<=floor(R/p[i]); ++j)
            if(1ll*p[i]*j-L >= 0)
              vis[1ll*p[i]*j - L] = 1;
        if(L==1) vis[0]=1;
        t=0;
        for(LL i=L; i<=R; ++i)
          if(!vis[i-L]) a[++t]=i;
        if(t<2) puts("There are no adjacent primes.");
        else
        {
          LL c1=a[1], c2=a[2], d1=a[1], d2=a[2];
          for(int i=2;i<t;++i)
          {
            if(a[i+1]-a[i] < c2-c1) c2=a[i+1], c1=a[i];
            if(a[i+1]-a[i] > d2-d1) d2=a[i+1], d1=a[i];
          }
          printf("%d,%d are closest, %d,%d are most distant.
    ",c1,c2,d1,d2);
        }
      }
      return 0;
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 1000003;
    
    int p[N], v[N], m;
    
    int main()
    {
      int n;
      cin >> n;
      for(int i=2;i<=n;++i)
      {
        if(!v[i]) {
          v[i] = p[++m] = i;
          int c=0;
          long long t=1ll*i;
          while(n/t)
          {
            c += n/t;
            t*=i;
          }
          printf("%d %d
    ", i, c);
        }
        for(int j=1;j<=m;++j)
        {
          if(p[j]>v[i] || p[j]>n/i) break;
          v[i*p[j]] = p[j];
        }
      }
      return 0;
    }
    
  • 相关阅读:
    查看端口有没有被占用
    微信公众号2()
    How to insert a segment of noise to music file
    puppet practice
    Docker Commands
    LempelZiv algorithm realization
    The algorithm of entropy realization
    Java network programmingguessing game
    Deploy Openstack with RDO and Change VNC console to Spice
    puppet overview
  • 原文地址:https://www.cnblogs.com/tztqwq/p/13946805.html
Copyright © 2011-2022 走看看