zoukankan      html  css  js  c++  java
  • 个人训练记录-赛码"bestcoder"杯中国大学生程序设计冠军赛

     A.Movie

      题意是给n个线段,要求求出是否存在三个不相交的线段,是的话输出yes,否则输出no。根据贪心的想法,可以先找出右端点r'最小的线段,他是三条线段中最左的那条,再找出左端点l'最大的线段,他是三条线段中最右的那条,这样我们只需要找出是否存在一条线段可以放在中间,即区间[l,r],l>r',r<l'。

      代码

     1 #include<cstdio>
     2 int n;
     3 long long L,R,l,r,a,b,c,d,mi,mx,flag,u,v,i;
     4 int main()
     5 {
     6     int test;
     7     long long P=4294967296;
     8     scanf("%d",&test);
     9     while(test--)
    10     {flag=0;
    11     scanf("%d%I64d%I64d%I64d%I64d%I64d%I64d",&n,&l,&r,&a,&b,&c,&d);
    12     L=l;R=r;
    13     u=L;v=R;
    14     mi=P;mx=0;
    15     if (u>v) u^=v^=u^=v;
    16     if (v<mi) mi=v;
    17     if (u>mx) mx=u;
    18     for (i=2;i<=n;i++)
    19     {
    20         L=(L*a+b)%P;
    21         R=(R*c+d)%P;
    22         u=L;v=R;
    23         if (u>v) u^=v^=u^=v;
    24         if (v<mi) mi=v;
    25         if (u>mx) mx=u;
    26     }
    27     L=l;R=r;
    28     u=l;v=r;if (u>v) u^=v^=u^=v;
    29         if ((u>mi)&&(v<mx)) flag=1;
    30     for (i=2;i<=n;i++)
    31     {
    32         if (flag) break;
    33         L=(L*a+b)%P;
    34         R=(R*c+d)%P;
    35         u=L;v=R;if (u>v) u^=v^=u^=v;
    36         if ((u>mi)&&(v<mx)) flag=1;
    37     }
    38     if (flag) printf("YES
    ");else printf("NO
    ");}
    39 }
    View Code

     B.Cycle

      题意是问给一张无向图,是否存在一个奇环或者偶环,环可以经过同样的点,做法是需要先求出dfs求出一颗树,一些边为树边,一些边为非树边,首先一条非树边和一些树边可以构成一些环,我们可以先判断这些环长度的奇偶性,然后如果一个环可能由多条非树边构成,需要怎么求,也很简单,如果存多个由一条非树边构成的环,他们交集非空,那么有他们复合成环的长度的奇偶性即为这些环的奇偶性的和,即使这些环的交集可能经过一些边,也不要紧,因为构成的环的边是否存在,是根据有多少个环包含这条边所决定,若存在奇数个环包含该边,则该边存在,否则不存在,因而复合环的奇偶性等价于这些环的奇偶性的和。

      代码

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include<cstdio>
      3 const int M = 601010;
      4 const int N = 201000;
      5 int vis[N],deep[N],jump[N][19],i,a[N],b[N],v[N][2];
      6 int dp,p[N],pre[M],tt[M],id[M],flag[N],n,m,Flag[2],s[N][2];
      7 void link(int x,int y,int z)
      8 {
      9     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;id[dp]=z;
     10 }
     11 void dfs(int x,int fa)
     12 {
     13     vis[x]=1;
     14     deep[x]=deep[fa]+1;
     15     jump[x][0]=fa;
     16     int i;
     17     for (i=1;i<=18;i++)
     18     jump[x][i]=jump[jump[x][i-1]][i-1];
     19     i=p[x];
     20     while (i)
     21     {
     22         if (!vis[tt[i]])
     23         {
     24             dfs(tt[i],x);
     25             flag[id[i]]=1;
     26         }
     27         i=pre[i];
     28     }
     29 }
     30 int lca(int a,int b)
     31 {
     32     if (deep[a]<deep[b]) a^=b^=a^=b;
     33     int i;
     34     for (i=18;i>=0;i--)
     35     if (deep[jump[a][i]]>=deep[b]) a=jump[a][i];
     36     if (a==b) return a;
     37     for (i=18;i>=0;i--)
     38     if (jump[a][i]!=jump[b][i])
     39     {
     40         a=jump[a][i];b=jump[b][i];
     41     }
     42     return jump[a][0];
     43 } 
     44 void gao(int x)
     45 {
     46     int i;
     47     s[x][0]+=v[x][0];
     48     s[x][1]+=v[x][1];
     49     i=p[x];
     50     while (i)
     51     {
     52         if (jump[tt[i]][0]==x)
     53         {    
     54             gao(tt[i]);
     55             s[x][0]+=s[tt[i]][0];
     56             s[x][1]+=s[tt[i]][1];
     57         }
     58         i=pre[i];
     59     }
     60     if (s[x][0]) Flag[0]=1;
     61     if (s[x][1]) Flag[1]=1;
     62     if (s[x][1]>=2) Flag[0]=1;
     63 }
     64 int main()
     65 {
     66     int test;
     67     scanf("%d",&test);
     68     while (test--)
     69     {
     70     scanf("%d%d",&n,&m);
     71     dp=0;
     72     for (i=1;i<=n;i++)
     73     p[i]=vis[i]=v[i][0]=v[i][1]=s[i][0]=s[i][1]=0;
     74     Flag[0]=Flag[1]=0;
     75     for (i=1;i<=m;i++)
     76     {
     77         flag[i]=0;
     78         scanf("%d%d",&a[i],&b[i]);
     79         link(a[i],b[i],i);
     80         link(b[i],a[i],i);    
     81     }
     82     for (i=1;i<=n;i++)
     83     if (vis[i]==0) dfs(i,0);
     84     for (i=1;i<=m;i++)
     85     if (!flag[i])
     86     {
     87         int c=lca(a[i],b[i]);
     88         int dis=(deep[a[i]]+deep[b[i]]-2*deep[c]+1)%2;
     89         v[jump[c][0]][dis]--;
     90         v[c][dis]--;
     91         v[a[i]][dis]++;
     92         v[b[i]][dis]++;
     93     }
     94     for (i=1;i<=n;i++)
     95     if (jump[i][0]==0) gao(i);
     96     if (Flag[1])
     97     printf("YES
    ");else printf("NO
    ");
     98     if (Flag[0])
     99     printf("YES
    ");else printf("NO
    ");
    100     }
    101 }
    View Code

     C.Segment

      假设对于一个可行的方案,若Ai<Aj,且Bpi>Bpj,那么[Ai,Bpi]∩[Aj,Bpj]与[Ai,Bpj]∩[Aj,Bpi]是等价的,因此我们可以一直将这样的pi和pj进行交换,直到不存在这样的方案,也就是说对于所有的可行方案,经过这样的交换后,配对都会变成一样的,因此可以将A与B进行排序。若存在Ai>Bi则不存在可行方案,否则找一个最长的输出即可。

      代码

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<math.h>
     4 #include<string.h>
     5 #include<stdlib.h>
     6 #include<algorithm>
     7 using namespace std;
     8 const int N= 1001010;
     9 int n,m,i,a[N],b[N],f[N],j,flag,cnt,ans;
    10 int main()
    11 {
    12     int test;
    13     scanf("%d",&test);
    14     while (test--)
    15     {
    16         ans=0;cnt=0;flag=0;
    17     scanf("%d%d",&n,&m);
    18         for (i=1;i<=n;i++) f[i]=0;
    19     for (i=1;i<=m;i++)
    20     scanf("%d",&a[i]);
    21     for (i=1;i<=m;i++)
    22     scanf("%d",&b[i]);
    23     sort(a+1,a+1+m);
    24     sort(b+1,b+1+m);
    25     for (i=1;i<=m;i++)
    26     {
    27         for (j=a[i];j<=b[i];j++)
    28         f[j]=1;
    29     if (a[i]>b[i]) 
    30     {
    31         flag=1;break;
    32     }
    33     }
    34     for (i=1;i<=n;i++)
    35     if (f[i]==0) cnt++;else
    36     {
    37         if (cnt>ans) ans=cnt;cnt=0;
    38     }
    39     if (cnt>ans) ans=cnt;
    40     if (flag) printf("Stupid BrotherK!
    ");
    41     else
    42     printf("%d.000000
    ",ans);
    43     }
    44 }
    View Code

     D.Brackets

       题意是给一个括号序列,支持两种操作,第一种是修改一个位置的括号,第二种是查询区间[L,R]中,第k个未匹配括号是哪一个,输出下标。若无解输出-1

       首先考虑有无解的判断,若一个序列中消除了已匹配的括号,那么未匹配括号必定是这种形式)))....)))(((((....((,我们可以根据前缀和来判断有无解,做法如下:

      先将'(’视为1,')'视为-1,维护括号序列每个位置的的前缀和sum,那么在区间[L,R]中,未匹配括号的个数即为sum[L-1]+sum[R]-2*min(sum[i])(L<=i<=R),区间最小的前缀和可以用线段树维护一下。

       然后考虑有解情况,若k<=sum[L-1]-sum[i],则答案为区间[l,r]中最靠左边的前缀和为sum[L-1]-k的括号的位置。否则为区间中最靠右边的,且前缀和为min(sum[i])+(k-(sum[L-1]-min(sum[i])))的括号的位置+1。

        用线段树维护一下前缀和最小值,即可进行上面解决方法的所有操作,复杂度O(nlogn)

      代码

      1 #include<cstdio>
      2 #include<set>
      3 #define fi first
      4 #define sc second
      5 using namespace std;
      6 typedef pair<int,int> P;
      7 const int N = 2001010;
      8 int v[N],e[N],n,m,i,o;
      9 P s[N];
     10 char ch[N];
     11 P min(P a,P b)
     12 {
     13     if (a.fi==b.fi) 
     14     {
     15         if (a.sc<b.sc) return a;return b;
     16     } 
     17     if (a.fi<b.fi) return a;return b;
     18 }
     19 void clean(int x)
     20 {
     21     if (v[x])
     22     {
     23         s[x].fi+=v[x];
     24         v[2*x]+=v[x];
     25         v[2*x+1]+=v[x];
     26         v[x]=0;
     27     }
     28 }
     29 void gao(int x,int l,int r)
     30 {
     31     v[x]=0;
     32     if (r-l==1)
     33     {
     34         s[x].fi=e[r];
     35         s[x].sc=r;
     36     }
     37     else
     38     {
     39         int m=(l+r)>>1;
     40         gao(2*x,l,m);
     41         gao(2*x+1,m,r);
     42         s[x]=min(s[2*x],s[2*x+1]);
     43     }
     44 }
     45 void change(int x,int a,int b,int l,int r,int c)
     46 {
     47     clean(x);
     48     if ((a<=l)&&(r<=b))
     49     {
     50         v[x]+=c;
     51         return;
     52     }
     53     int m=(l+r)>>1;
     54     if (a<m) change(2*x,a,b,l,m,c);
     55     if (m<b) change(2*x+1,a,b,m,r,c);
     56     clean(2*x);clean(2*x+1);
     57     s[x]=min(s[2*x],s[2*x+1]);
     58 }
     59 P query(int x,int a,int b,int l,int r)
     60 {
     61     clean(x);
     62     if ((a<=l)&&(r<=b)) return s[x];
     63     int m=(l+r)>>1;
     64     P tmp;tmp.fi=1000000000;
     65     if (a<m) tmp=min(tmp,query(2*x,a,b,l,m));
     66     if (m<b) tmp=min(tmp,query(2*x+1,a,b,m,r));
     67     return tmp; 
     68 }
     69 int get(int x,int a,int b,int l,int r,int c,int typ)
     70 {
     71     clean(x);
     72     if (s[x].fi>c) return 0;
     73     int m=(l+r)>>1;
     74     int ans=0;
     75     if (r-l==1) 
     76     {
     77         if (s[x].fi==c) return r;else return 0;
     78     }
     79     if ((a<=l)&&(r<=b))
     80     {
     81         if (typ==0)
     82         {
     83             ans=get(2*x,a,b,l,m,c,typ);
     84             if (ans) return ans;
     85             ans=get(2*x+1,a,b,m,r,c,typ);
     86             return ans;
     87         }
     88         else
     89         {    
     90             ans=get(2*x+1,a,b,m,r,c,typ);
     91             if (ans) return ans;
     92             ans=get(2*x,a,b,l,m,c,typ);
     93             return ans;
     94         }
     95     }
     96     if (typ==0)
     97     {
     98     if (a<m) ans=get(2*x,a,b,l,m,c,typ);
     99     if (ans) return ans;
    100     if (m<b) ans=get(2*x+1,a,b,m,r,c,typ);
    101     return ans;
    102     }
    103     else
    104     {
    105     if (m<b) ans=get(2*x+1,a,b,m,r,c,typ);
    106     if (ans) return ans;
    107     if (a<m) ans=get(2*x,a,b,l,m,c,typ);
    108     return ans;
    109     }
    110 }
    111 int main()
    112 {
    113     int test;
    114     scanf("%d",&test);
    115     while (test--)
    116     {
    117     scanf("%d%d",&n,&m);
    118     for (i=1;i<=n;i++)
    119     scanf(" %c",&ch[i]);
    120     for (i=1;i<=n;i++)
    121     if (ch[i]=='(') e[i+1]=e[i]+1;else e[i+1]=e[i]-1;
    122     gao(1,0,n+1);
    123     for (i=1;i<=m;i++)
    124     {
    125         int typ,a,b,c;
    126         scanf("%d",&typ);
    127         if (typ==1)
    128         {
    129             scanf("%d",&a);
    130             if (ch[a]=='(')
    131             {
    132                 ch[a]=')';
    133                 a++;
    134                 change(1,a-1,n+1,0,n+1,-2);
    135             }
    136             else
    137             {
    138                 ch[a]='(';
    139                 a++;
    140                 change(1,a-1,n+1,0,n+1,2);
    141             }
    142         }
    143         else
    144         {
    145             scanf("%d%d%d",&a,&b,&c);
    146             a++;b++;
    147             P tmp=query(1,a-2,b,0,n+1);
    148     
    149             int p=0,q=0;
    150             p=query(1,a-2,a-1,0,n+1).fi;
    151             q=query(1,b-1,b,0,n+1).fi;
    152 
    153             if (p-tmp.fi+q-tmp.fi<c)
    154                 printf("-1
    ");
    155             else
    156             if (c<=p-tmp.fi)
    157                 printf("%d
    ",get(1,a-1,n+1,0,n+1,p-c,0)-1);
    158             else
    159                 printf("%d
    ",get(1,0,b,0,n+1,tmp.fi+c-(p-tmp.fi)-1,1));
    160         }
    161     }
    162     }
    163 } 
    View Code

     E.Game

        题意是有n个人站成环,有一个集合S,每次从集合S中随机选出一个数字s,然后依次报数,报道s的人从环中出去,问n轮后有哪些人有获胜的可能性。经典的约瑟夫问题,可以O(N^3)dp解决。

       代码

     1 #include<cstdio>
     2 const int N = 1010;
     3 int n,m,i,j,k,t,a[N],f[N][N],ans;
     4 int main()
     5 {
     6     int test;
     7     scanf("%d",&test);
     8     while (test--)
     9     {
    10     scanf("%d%d",&n,&m);
    11     for (i=1;i<=m;i++)
    12     scanf("%d",&a[i]);
    13     for (i=0;i<=n;i++)
    14     for (j=0;j<=n;j++)
    15     f[i][j]=0;
    16     f[1][0]=1;
    17     for (i=2;i<=n;i++)
    18     {
    19         for (j=1;j<=m;j++)
    20         {
    21             t=(a[j]-1)%i;
    22             for (k=0;k<i;k++)
    23             if (f[i-1][k])
    24             f[i][(t+1+k)%i]=1;
    25         }
    26     }
    27     ans=0;
    28     for (i=0;i<n;i++)
    29     if (f[n][i]) ans++;
    30     printf("%d
    ",ans);
    31     int flag=0;
    32     for (i=0;i<n;i++)
    33     if (f[n][i])
    34     {
    35         if (flag) printf(" ");
    36         flag=1; 
    37         printf("%d",i+1);
    38     }
    39     printf("
    ");
    40     }    
    41 }
    View Code

      

      F.

      G.

      H.Occupation

      题意是给一棵树,树上每个点都有一个权值,有三类操作,1.取一条路径上所有的没被取的点,2.如果x点被取了,则将其变为未取的状态,3.去以x为根的子树上所有没被取的点,每次操作后求出被取点的价值总和。

      裸的树链剖分。。。

      代码

      1 #include<cstdio>
      2 const int N = 1010101;
      3 int dp,pre[N],p[N],tt[N],size[N],id[N],f[N],deep[N],go[N],L[N],R[N];
      4 int cnt,gf[N],i,n,e[N],a,b,v[N],s[N],sum[N];
      5 void link(int x,int y)
      6 {
      7     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
      8 }
      9 void dfs1(int x,int y)
     10 {
     11     size[x]=1;
     12     int i=p[x];
     13     while (i)
     14     {
     15         if (tt[i]!=y)
     16         {
     17             f[tt[i]]=x;
     18             deep[tt[i]]=deep[x]+1;
     19             dfs1(tt[i],x);
     20             size[x]+=size[tt[i]];
     21             if (size[tt[i]]>size[go[x]]) go[x]=tt[i];
     22         }
     23         i=pre[i];
     24     }
     25 }
     26 void dfs2(int x,int y)
     27 {
     28     L[x]=++cnt;
     29     id[cnt]=x; 
     30     gf[x]=y;
     31     if (go[x]) dfs2(go[x],y);
     32     int i=p[x];
     33     while (i)
     34     {
     35         if (deep[tt[i]]>deep[x])
     36         if (tt[i]!=go[x])
     37         dfs2(tt[i],tt[i]);
     38         i=pre[i];
     39     }
     40     R[x]=cnt;
     41 }
     42 void clean(int x)
     43 {
     44     if (v[x]) 
     45     {
     46         v[x]=0;
     47         s[x]=sum[x];
     48         v[2*x]=1;
     49         v[2*x+1]=1;
     50     }
     51 }
     52 void change(int x,int a,int b,int l,int r,int c)
     53 {
     54     clean(x);
     55     if ((a<=l)&&(r<=b))
     56     {
     57         if (c) v[x]=1;else s[x]=0;
     58         return;
     59     }
     60     int m=(l+r)>>1;
     61     if (a<m) change(2*x,a,b,l,m,c);
     62     if (m<b) change(2*x+1,a,b,m,r,c);
     63     clean(2*x);clean(2*x+1);
     64     s[x]=s[2*x]+s[2*x+1];
     65 }
     66 void gao(int a,int b)
     67 {
     68     while (1)
     69     {
     70         if (deep[gf[a]]<deep[gf[b]]) a^=b^=a^=b;
     71         if (gf[a]==gf[b])
     72         {
     73             if (deep[a]<deep[b]) a^=b^=a^=b;
     74             change(1,L[b]-1,L[a],0,n,1);
     75             return;
     76         }
     77         else
     78         {
     79             change(1,L[gf[a]]-1,L[a],0,n,1);
     80             a=f[gf[a]];
     81         }
     82     }
     83 }
     84 void get(int x,int l,int r)
     85 {
     86     v[x]=s[x]=0;
     87     if (r-l==1)
     88     {
     89         sum[x]=e[id[r]];
     90         return;
     91     }
     92     int m=(l+r)>>1;
     93     get(2*x,l,m);
     94     get(2*x+1,m,r);
     95     sum[x]=sum[2*x]+sum[2*x+1];
     96 }
     97 int main()
     98 {
     99     int test;
    100     scanf("%d",&test);
    101     while (test--)
    102     {
    103     scanf("%d",&n);dp=cnt=0;
    104     for (i=1;i<=n;i++)
    105     {
    106         scanf("%d",&e[i]);
    107         p[i]=go[i]=deep[i]=gf[i]=f[i]=0;
    108     }
    109     for (i=1;i<n;i++)
    110     {
    111         scanf("%d%d",&a,&b);
    112         link(a,b);link(b,a);
    113     }
    114     dfs1(1,0);
    115     dfs2(1,1);
    116     get(1,0,n);
    117     int m;
    118     scanf("%d",&m);
    119     for (i=1;i<=m;i++)
    120     {
    121         int typ;
    122         scanf("%d",&typ);
    123         if (typ==1)
    124         {
    125             scanf("%d%d",&a,&b);
    126             gao(a,b);
    127         }
    128         else
    129         {
    130             scanf("%d",&a);
    131             if (typ==2)
    132                 change(1,L[a]-1,L[a],0,n,0);
    133             else
    134                 change(1,L[a]-1,R[a],0,n,1);
    135         }
    136         clean(1);
    137         printf("%d
    ",s[1]);
    138     }
    139     }
    140 }
    View Code

      I.Exploration

      题意是给一张图,其中有一些边为双向,有一些为单向,问是否存在一个起点,其能走出一条路径,至少能到达一个起点以外的点,且最终能回到起点,注意路一旦经过,就会坍塌。

      可以先将双向边连接的点用并查集并起来,如果一个集合中的点不构成一颗树,则说明存在环,那么这个环就可以视为答案,输出YES,如果所有集合都是生成树,那么接着考虑有向边,如果有向边连接的两个点属于同一集合,则存在环经过该有向边,可以直接输出YES,否则则将两端点所在的集合连边,最后进行一边拓扑排序,判断是否存在环,如果存在环输出YES,否则输出NO

          代码

     1 #include<cstdio>
     2 #include<queue>
     3 using namespace std;
     4 const int N = 2010101;
     5 int f[N],n,m1,m2,l[N],r[N],i,a,b,id[N],cnt,rd[N];
     6 int dp,pre[N],p[N],tt[N],vis[N];
     7 queue<int> Q;
     8 int gf(int x)
     9 {
    10     int t,p;
    11     p=x;
    12     while (p!=f[p]) p=f[p];
    13     while (x!=p)
    14     {
    15         t=f[x];
    16         f[x]=p;
    17         x=t;
    18     }
    19     return p;
    20 }
    21 void link(int x,int y)
    22 {
    23     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
    24 }
    25 int main()
    26 {
    27     int test;
    28     scanf("%d",&test);
    29     while (test--)
    30     {
    31     scanf("%d%d%d",&n,&m1,&m2);
    32     for (i=1;i<=m1;i++)
    33     scanf("%d%d",&l[i],&r[i]);
    34     for (i=1;i<=m2;i++)
    35     scanf("%d%d",&l[m1+i],&r[m1+i]);
    36     dp=0;
    37     for (i=1;i<=n;i++) f[i]=i,id[i]=rd[i]=p[i]=vis[i]=0;
    38     for (i=1;i<=m1;i++)
    39     {
    40         if (l[i]==r[i]) continue;
    41         a=gf(l[i]);b=gf(r[i]);
    42         if (a==b) break;
    43         f[a]=b;
    44     }
    45     if (i<=m1)
    46     {
    47         printf("YES
    ");
    48         continue;
    49     }
    50     cnt=0;
    51     for (i=1;i<=n;i++)
    52     {    
    53         if (id[gf(i)]==0) id[gf(i)]=++cnt;
    54         id[i]=id[gf(i)];
    55     }
    56     for (i=m1+1;i<=m1+m2;i++)
    57     {
    58         if (l[i]==r[i]) continue;
    59         if (id[l[i]]==id[r[i]]) break;
    60         link(id[l[i]],id[r[i]]);
    61         rd[id[r[i]]]++; 
    62     } 
    63     if(i<=m1+m2)
    64     {
    65         printf("YES
    ");
    66         continue;
    67     }
    68     for (i=1;i<=cnt;i++)
    69     if (rd[i]==0) Q.push(i);
    70     while (!Q.empty())
    71     {
    72         int x=Q.front();Q.pop();
    73         i=p[x];
    74         while (i)
    75         {
    76             rd[tt[i]]--;
    77             if (!rd[tt[i]]) Q.push(tt[i]);
    78             i=pre[i];
    79         }
    80     } 
    81     for (i=1;i<=cnt;i++)
    82     if (rd[i]) break;
    83     if (i<=cnt) printf("YES
    ");else printf("NO
    ");
    84     }
    85 }
    View Code

     J.GCD

         题意是给一些询问,每次询问区间[L,R]的gcd是多少,且得到的答案为w,问能否构造出一个使得所有询问都满足的答案,如果存在多个方案,输出一个序列和最小的方案。

         一开始设序列所有数字为1,对于一个询问[L,R]我们可以把区间[L,R]中的数字ai变为lcm(ai,w),这样就可以构造出一个序列,最后用询问来验证一下这个序列是否合法,如果合法,那么该序列即为最小方案,若不合法即为无解。

      代码

     1 #include<cstdio>
     2 const int N = 101010;
     3 int n,m,i,j,l[N],r[N],w[N],test,tmp;
     4 long long a[N];
     5 long long gcd(long long a,long long b)
     6 {
     7     if (b==0) return a;
     8     return gcd(b,a%b);
     9 }
    10 int main()
    11 {
    12     scanf("%d",&test);
    13     while (test--)
    14     {
    15     scanf("%d%d",&n,&m);
    16     for (i=1;i<=m;i++)
    17     scanf("%d%d%d",&l[i],&r[i],&w[i]);
    18     for (i=1;i<=n;i++)
    19     {
    20         a[i]=1;
    21         for (j=1;j<=m;j++)
    22         if ((l[j]<=i)&&(i<=r[j]))
    23         {
    24             a[i]=(a[i]*w[j])/gcd(a[i],w[j]);
    25             if (a[i]>1000000000) break;
    26         }
    27         if (a[i]>1000000000) break;
    28     }
    29     if (i<=n)
    30     printf("Stupid BrotherK!
    ");
    31     else
    32     {
    33         for (i=1;i<=m;i++)
    34         {
    35             tmp=0;
    36             for (j=l[i];j<=r[i];j++)
    37             tmp=gcd(tmp,a[j]);
    38             if (tmp!=w[i]) break;
    39         }
    40         if (i<=m) printf("Stupid BrotherK!
    ");
    41         else
    42         {
    43             for (i=1;i<n;i++)
    44             printf("%I64d ",a[i]);printf("%I64d
    ",a[n]);
    45         }
    46     }
    47     }
    48 }
    View Code
  • 相关阅读:
    关押罪犯
    食物链
    归并排序(分治)
    并查集+路径压缩
    3的幂的和
    斐波那契数列的第N项
    0和5
    扔盘子
    线段相交
    回文字符串
  • 原文地址:https://www.cnblogs.com/fzmh/p/5583765.html
Copyright © 2011-2022 走看看