zoukankan      html  css  js  c++  java
  • Minieye杯第十五届华中科技大学程序设计邀请赛现场同步赛

    良心的题目和解法,quite bad的题面和题解。。。

    AMatrix

    原题。。。

    from https://codeforces.com/problemset/problem/811/E

    E. Vladik and Entertaining Flags

    线段树+并查集

    见代码注释

    时间复杂度:

    在正常线段树的基础上,

    每两列的合并O(n),常数较大

    build:总共合并n次,O(n^2)

    query:

    如最坏情况

    n=2^k

    1~n-1

    需要合并判断

    1~n/2 与 n/2+1~n/2

    n/2+1~n/4*3 与 n/4*3+1~n

    ……

    共k次,可认为是log(n)次

    q次询问,O(q * log(n)*n)

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15 const int maxm=10;
     16 
     17 /**
     18 两个小区间合并成一个小区间:
     19 左区间最右边的一列 右区间最左边的一列 combined using 并查集
     20 
     21 一个区间的数目为:
     22 两个小区间的数目之和 - 两个小区间交界部分相同的数目
     23 **/
     24 
     25 struct node
     26 {
     27     ///左区间最右边的一列 右区间最左边的一列 连通块数目
     28     int left[maxm],right[maxm],cnt;
     29 }f[maxn<<2];
     30 
     31 int n,m,id;
     32 int a[maxn][10],fa[maxn*10],tl[maxm],tr[maxm];
     33 
     34 int getf(int d)
     35 {
     36     if (fa[d]==d)
     37         return d;
     38     fa[d]=getf(fa[d]);
     39     return fa[d];
     40 }
     41 
     42 ///从小到大,处理[区间1_left,区间2_right],保证区间1和区间2已经处理完毕
     43 void merge_interval(node &x,node &y,node &z,int pos)
     44 {
     45     int i,cnt=0;
     46     memcpy(tl,y.right,n*4);///
     47     memcpy(tr,z.left,n*4);///
     48     ///must
     49     ///不修改之前的数值
     50     for (i=0;i<n;i++)
     51     {
     52         fa[tl[i]]=tl[i];
     53         fa[tr[i]]=tr[i];
     54         fa[y.left[i]]=y.left[i];///
     55         fa[z.right[i]]=z.right[i];///
     56     }
     57     for (i=0;i<n;i++)
     58         if (a[pos][i]==a[pos+1][i])
     59         {
     60             tl[i]=getf(tl[i]);
     61             tr[i]=getf(tr[i]);
     62             if (tl[i]!=tr[i])
     63             {
     64                 fa[tl[i]]=tr[i];
     65                 cnt++;
     66             }
     67             /**
     68             在之前还没被合并,见例子
     69             1 1 1 yes
     70             1 2 1
     71             1 1 1 no
     72             **/
     73         }
     74 
     75     x.cnt=y.cnt+z.cnt-cnt;
     76     ///经过两列合并的修改(左边/右边列的哪些原来不属于同一个集合的两个数,经过合并后,属于同一个集合)
     77     for (i=0;i<n;i++)
     78     {
     79         x.left[i]=getf(y.left[i]);
     80         x.right[i]=getf(z.right[i]);
     81     }
     82 }
     83 
     84 void build(int ind,int l,int r)
     85 {
     86     if (l==r)
     87     {
     88         ///一列中连续的数字的父亲相同即可
     89         int cnt=0,i;
     90         for (i=0;i<n;i++)
     91         {
     92             if (i==0 || a[l][i]!=a[l][i-1])
     93                 id++,cnt++;
     94             f[ind].left[i]=f[ind].right[i]=id;
     95         }
     96         f[ind].cnt=cnt;
     97         return ;
     98     }
     99 
    100     int m=(l+r)>>1;
    101     build(ind<<1,l,m);
    102     build(ind<<1|1,m+1,r);
    103 
    104     merge_interval(f[ind],f[ind<<1],f[ind<<1|1],m);
    105 }
    106 
    107 node query(int ind,int l,int r,int x,int y)
    108 {
    109     if (x<=l && r<=y)
    110         return f[ind];
    111     int m=(l+r)>>1;
    112     node u,v,w;
    113     if (x<=m)
    114         u=query(ind<<1,l,m,x,y);
    115     if (m<y)
    116         v=query(ind<<1|1,m+1,r,x,y);
    117     ///不改变f[ind<<1]和f[ind<<1|1]的值
    118 
    119     if (x<=m && m<y)
    120     {
    121         merge_interval(w,u,v,m);
    122         return w;
    123     }
    124     else if (x<=m)
    125         return u;
    126     else
    127         return v;
    128 }
    129 
    130 int main()
    131 {
    132     int Q,i,j;
    133     scanf("%d%d%d",&n,&m,&Q);
    134     for (i=0;i<n;i++)
    135         for (j=0;j<m;j++)
    136             scanf("%d",&a[j][i]);
    137 
    138     build(1,0,m-1);
    139 
    140     while (Q--)
    141     {
    142         scanf("%d%d",&i,&j);
    143         i--,j--;
    144         printf("%d
    ",query(1,0,m-1,i,j).cnt);
    145     }
    146 
    147     return 0;
    148 }
    149 /*
    150 x 1 y
    151 
    152 
    153 3 3 4
    154 1 1 1
    155 1 2 1
    156 1 1 1
    157 1 3
    158 wrong
    159 1 =1
    160 1->2 0
    161 2->3 -1
    162 实际上,第二列的两个数,在第一列中
    163 
    164 5 3 4
    165 1 1 1
    166 1 2 1
    167 1 1 1
    168 1 2 1
    169 1 1 1
    170 2 3
    171 1 2
    172 1 3
    173 
    174 4 5 10
    175 1 1 2 1 1
    176 2 1 2 3 1
    177 1 1 1 2 1
    178 2 4 1 1 1
    179 2 4
    180 2 5
    181 1 4
    182 1 5
    183 
    184 1 15 10
    185 1 1 1 1 2 1 2 2 3 2 2 1 1 1 10000
    186 1 15
    187 2 6
    188 3 10
    189 4 8
    190 
    191 4 10 10
    192 7 9 4 3 1 9 4 7 1 7
    193 1 3 8 7 8 5 7 9 1 7
    194 7 2 2 3 7 7 1 6 5 9
    195 6 7 9 4 2 5 8 5 7 2
    196 2 6
    197 
    198 */

    其它类似题目:

    hdu6392 Reverse Game

    可持久化(https://www.luogu.org/problem/P3402)

    [WC2005]双面棋盘
    https://www.luogu.org/problem/P4121

    -------------------------

    我之前错误的方法

    k列->k+1列的变化

    cal(k,k+1)-cal(k,k)

    x~y: 第x列 + k列->k+1列 + k+1列->k+2列 -> y-1列->y列

    线段树

    无法用于

    3 3 4
    1 1 1
    1 2 1
    1 1 1
    1 3

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15  
     16 /**
     17 try to save memory as much as possible
     18 **/
     19  
     20 int a[10][maxn],n,m,qx[maxn*10],qy[maxn*10];
     21  
     22 int f[maxn<<2],g[maxn],z[maxn];
     23 bool vis[10][maxn];
     24  
     25 int dx[4]={-1,0,0,1};
     26 int dy[4]={0,-1,1,0};
     27  
     28 int cal(int yl,int yr)
     29 {
     30     int cnt=0,i,j,k,head,tail,x,y,xx,yy;
     31     for (i=0;i<=n-1;i++)
     32         for (j=yl;j<=yr;j++)
     33             vis[i][j]=0;
     34     for (i=0;i<=n-1;i++)
     35         for (j=yl;j<=yr;j++)
     36             if (!vis[i][j])
     37             {
     38                 head=0,tail=1;
     39                 qx[1]=i,qy[1]=j;
     40                 while (head<tail)
     41                 {
     42                     head++;
     43                     x=qx[head];
     44                     y=qy[head];
     45                     for (k=0;k<4;k++)
     46                     {
     47                         xx=x+dx[k];
     48                         yy=y+dy[k];
     49                         if (xx>=0 && xx<=n-1 && yy>=yl && yy<=yr && !vis[xx][yy] && a[x][y]==a[xx][yy])
     50                         {
     51                             qx[++tail]=xx;
     52                             qy[tail]=yy;
     53                             vis[xx][yy]=1;
     54                         }
     55                     }
     56                 }
     57                 cnt++;
     58             }
     59     return cnt;
     60 }
     61  
     62 void build(int ind,int l,int r)
     63 {
     64     if (l==r)
     65         z[ind]=f[l];
     66     else
     67     {
     68         int m=(l+r)>>1;
     69         build(ind<<1,l,m);
     70         build(ind<<1|1,m+1,r);
     71         z[ind]=z[ind<<1]+z[ind<<1|1];
     72     }
     73 }
     74  
     75 int query(int ind,int l,int r,int x,int y)
     76 {
     77     if (x<=l && r<=y)
     78         return z[ind];
     79     int m=(l+r)>>1,sum=0;
     80     if (x<=m)
     81         sum+=query(ind<<1,l,m,x,y);
     82     if (m<y)
     83         sum+=query(ind<<1|1,m+1,r,x,y);
     84     return sum;
     85 }
     86  
     87 int main()
     88 {
     89     int Q,i,j;
     90     scanf("%d%d%d",&n,&m,&Q);
     91     for (j=0;j<n;j++)
     92         for (i=0;i<m;i++)
     93             scanf("%d",&a[j][i]);
     94  
     95     ///pth -> (p+1)th the number of blocks changes f[l][p+1]
     96 //            printf("l=%d
    ",l);
     97     for (i=0;i<m;i++)
     98         g[i]=cal(i,i);    ///can also calculate when querying
     99     for (i=1;i<m;i++)
    100         f[i]=cal(i-1,i)-g[i-1];
    101  
    102     build(1,0,m-1);
    103  
    104     while (Q--)
    105     {
    106         scanf("%d%d",&i,&j);
    107         i--,j--;
    108         printf("%d
    ",(i==j?0:query(1,0,m-1,i+1,j)) + g[i]);   ///注意优先级,一定要加括号
    109     }
    110  
    111     return 0;
    112 }
    113 /*
    114 10 1 10
    115 1
    116 2
    117 1
    118 1
    119 1
    120 1
    121 2
    122 1
    123 3
    124 1
    125 */

    错误代码

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15  
     16 /**
     17 try to save memory as much as possible
     18 **/
     19  
     20 int a[10][maxn],n,m,qx[maxn*10],qy[maxn*10];
     21  
     22 int f[maxn<<2],g[maxn],z[maxn];
     23 bool vis[10][maxn];
     24  
     25 int dx[4]={-1,0,0,1};
     26 int dy[4]={0,-1,1,0};
     27  
     28 int cal(int yl,int yr)
     29 {
     30     int cnt=0,i,j,k,head,tail,x,y,xx,yy;
     31     for (i=0;i<=n-1;i++)
     32         for (j=yl;j<=yr;j++)
     33             vis[i][j]=0;
     34     for (i=0;i<=n-1;i++)
     35         for (j=yl;j<=yr;j++)
     36             if (!vis[i][j])
     37             {
     38                 head=0,tail=1;
     39                 qx[1]=i,qy[1]=j;
     40                 while (head<tail)
     41                 {
     42                     head++;
     43                     x=qx[head];
     44                     y=qy[head];
     45                     for (k=0;k<4;k++)
     46                     {
     47                         xx=x+dx[k];
     48                         yy=y+dy[k];
     49                         if (xx>=0 && xx<=n-1 && yy>=yl && yy<=yr && !vis[xx][yy] && a[x][y]==a[xx][yy])
     50                         {
     51                             qx[++tail]=xx;
     52                             qy[tail]=yy;
     53                             vis[xx][yy]=1;
     54                         }
     55                     }
     56                 }
     57                 cnt++;
     58             }
     59     return cnt;
     60 }
     61  
     62 void build(int ind,int l,int r)
     63 {
     64     if (l==r)
     65         z[ind]=f[l];
     66     else
     67     {
     68         int m=(l+r)>>1;
     69         build(ind<<1,l,m);
     70         build(ind<<1|1,m+1,r);
     71         z[ind]=z[ind<<1]+z[ind<<1|1];
     72     }
     73 }
     74  
     75 int query(int ind,int l,int r,int x,int y)
     76 {
     77     if (x<=l && r<=y)
     78         return z[ind];
     79     int m=(l+r)>>1,sum=0;
     80     if (x<=m)
     81         sum+=query(ind<<1,l,m,x,y);
     82     if (m<y)
     83         sum+=query(ind<<1|1,m+1,r,x,y);
     84     return sum;
     85 }
     86  
     87 int main()
     88 {
     89     int Q,i,j;
     90     scanf("%d%d%d",&n,&m,&Q);
     91     for (j=0;j<n;j++)
     92         for (i=0;i<m;i++)
     93             scanf("%d",&a[j][i]);
     94  
     95     ///pth -> (p+1)th the number of blocks changes f[l][p+1]
     96 //            printf("l=%d
    ",l);
     97     for (i=0;i<m;i++)
     98         g[i]=cal(i,i);    ///can also calculate when querying
     99     for (i=1;i<m;i++)
    100         f[i]=cal(i-1,i)-g[i-1];
    101  
    102     build(1,0,m-1);
    103  
    104     while (Q--)
    105     {
    106         scanf("%d%d",&i,&j);
    107         i--,j--;
    108         printf("%d
    ",(i==j?0:query(1,0,m-1,i+1,j)) + g[i]);   ///注意优先级,一定要加括号
    109     }
    110  
    111     return 0;
    112 }
    113 /*
    114 10 1 10
    115 1
    116 2
    117 1
    118 1
    119 1
    120 1
    121 2
    122 1
    123 3
    124 1
    125 */

    BMistake

    树上差分

    之后补题

    CMassive

    每个区间都有它的作用域

    按照起始位置对区间进行排序

    meet in begin point +1

    meet in end point -1

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <set>
      7 #include <map>
      8 #include <list>
      9 #include <queue>
     10 #include <vector>
     11 #include <bitset>
     12 #include <algorithm>
     13 #include <iostream>
     14 using namespace std;
     15 #define ll long long
     16  
     17 const double eps=1e-8;
     18 const ll inf=1e18;
     19 const int maxn=1e6+10;
     20  
     21 ///主席树可做 1~i的所有前缀和建线段树(i=1,2,...,n)
     22  
     23 int num[maxn],f[maxn];
     24 ll pf[maxn],b[maxn];
     25  
     26 struct node
     27 {
     28     ll x;
     29     int ind;
     30     bool operator<(const node &y) const
     31     {
     32         return x<y.x;
     33     }
     34 }a[maxn];
     35  
     36 ll cal(int j)
     37 {
     38     ll sum=0;
     39     while (j>=1)
     40     {
     41         sum+=f[j];
     42         j-=j&-j;
     43     }
     44     return sum;
     45 }
     46  
     47 int main()
     48 {
     49     int n,l,r,m,i,j;
     50     ll *k;
     51     ll s,x,sum=0,v;
     52     cin>>n>>l>>r>>s;
     53 //    scanf("%d%d%d%lld",&n,&l,&r,&s);
     54     for (i=1;i<=n;i++)
     55     {
     56 //        scanf("%lld",&x);
     57         cin>>x;
     58         pf[i]=pf[i-1]+x;
     59         a[i].x=pf[i];
     60         a[i].ind=i;
     61     }
     62     sort(a+1,a+n+1);
     63     a[0].x=a[1].x-1;
     64     m=0;
     65     for (i=1;i<=n;i++)
     66     {
     67         if (a[i].x!=a[i-1].x)
     68         {
     69             m++;
     70             b[m]=a[i].x;
     71         }
     72         num[a[i].ind]=m;
     73     }
     74  
     75     for (i=1;i<=n;i++)
     76     {
     77         j=num[i];
     78         while (j<=m)
     79         {
     80             f[j]++;
     81             j+=j&-j;
     82         }
     83  
     84  
     85         if (i>=l-1 && i<=n-1)
     86         {
     87             v=pf[i-l+1]+s;
     88             k=lower_bound(b+1,b+m+1,v);
     89             sum-=i-cal(k-b-1);
     90         }
     91  
     92         if (i>=r)
     93         {
     94             j=i-r+l-1;
     95             v=pf[i-r]+s;
     96             k=lower_bound(b+1,b+m+1,v);
     97             sum+=i-cal(k-b-1);
     98         }
     99     }
    100  
    101     for (i=n-r+1+1;i<=n-l+1;i++)
    102     {
    103         v=pf[i-1]+s;
    104         k=lower_bound(b+1,b+m+1,v);
    105         sum+=n-cal(k-b-1);
    106     }
    107  
    108     printf("%lld",sum);
    109     return 0;
    110 }
    111 /*
    112 5 2 3 -100
    113 1 2 -3 4 5
    114  
    115 5 1 1 1
    116 1 2 -3 4 5
    117  
    118 1 1 1 1
    119 2
    120  
    121 3 3 3 0
    122 1 -1 2
    123  
    124 3 2 2 0
    125 1 -1 2
    126  
    127 3 2 3 0
    128 1 -1 2
    129  
    130 3 2 3 1
    131 1 -1 2
    132 */

    DModule

    学习了!

    dp式子

    ->

    系数固定,可使用快速幂

    ->

    状态矩阵满足规律,可降低时间复杂度

    然而数据的精度很xxx(哗啦哗啦)。

     矩阵特性:一行的数值为上一行的数值平移一个单位得到,且不会随运算改变。所以只用记录一行的状态。所以矩阵相乘时,只需要得到一行的结果,即O(n^2)。

    矩阵乘法操作

    a^k * a^k =a^(2k)

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e3+10;
     15  
     16 /**
     17 题目精度设得特别不好
     18 用long double,只能33.3%过
     19 用同样正确的方法(矩阵其它写法),也是没过
     20  
     21  
     22 每个数都选一遍,最后除以m
     23 [ f[i-1][j-1]+(f[i-1][j]*m-f[i-1][j]) ]/m
     24  
     25 -f[i-1][j] 数j各有一次被选中
     26  
     27 **/
     28  
     29 double a[maxn];
     30 int n;
     31  
     32 struct mat
     33 {
     34     double a[maxn];
     35     mat()
     36     {
     37         memset(a,0,sizeof(a));   ///一定要,不知道为什么
     38     }
     39     void init()
     40     {
     41         a[0]=1;
     42     }
     43     mat operator*(const mat &y) const
     44     {
     45         mat z;
     46         for (int i=0;i<n;i++)
     47             for (int j=0;j<n;j++)
     48                 z.a[(i+j)%n]+=a[i]*y.a[j];
     49         return z;
     50     }
     51 };
     52  
     53 mat mul(mat a,ll b)
     54 {
     55     mat y;
     56     y.init();
     57     while (b)
     58     {
     59         if (b&1)
     60             y=y*a;
     61         a=a*a;
     62         b>>=1;
     63     }
     64     return y;
     65 }
     66  
     67 int main()
     68 {
     69 //    FILE *in=fopen("data.in","r");
     70 //    FILE *out=fopen("data.out","w");
     71     ll m,k,i,j;
     72     mat ori,y;
     73     double tot;
     74 //    fscanf(in,"%lld%lld%lld",&n,&m,&k);
     75     scanf("%lld%lld%lld",&n,&m,&k);
     76     for (i=0;i<n;i++)
     77 //        fscanf(in,"%lf",&a[i]);
     78         scanf("%lf",&a[i]);
     79  
     80 //    ori.a[0]=1-1.0/m;
     81 //    ori.a[n-1]=1.0/m;
     82  
     83     ori.a[0]=1.0-1.0/m;
     84     ori.a[1]=1.0/m;
     85  
     86     y=mul(ori,k);
     87  
     88     for (i=0;i<n;i++)
     89     {
     90         tot=0;
     91         for (j=0;j<n;j++)
     92             tot+=y.a[j]*a[(i-j+n)%n];
     93 //            tot+=y.a[(j-i+n)%n]*a[j];
     94 //        fprintf(out,"%.1f%c",tot,i==n-1?'
    ':' ');
     95         printf("%.1f%c",tot,i==n-1?'
    ':' ');
     96     }
     97 //    fclose(in);
     98 //    fclose(out);
     99     return 0;
    100 }
    101 /*
    102 2 3 1
    103 3 0
    104 */

    EManhattan

    裸的bfs+二分答案

    二分实现次数 log(M) 大约为10

    一个更直观的方法是

    求每个A点能否访问所有B点,赋予属性 [n^2]

    然后求A点之间互相访问的情况,

    一个集合,互相访问,则至少集合中有一个点,能访问所有的B点。 [N]

    题解用并查集,也行。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=2e3+10;
     15 
     16 struct node
     17 {
     18     int x,y;
     19 }a[maxn];
     20 
     21 bool vis[maxn];
     22 int q[maxn],dist[maxn][maxn],use[maxn];
     23 
     24 int main()
     25 {
     26     int n,m,g,i,j,k,l,r,mid,sum1,sum2,head,tail,d;
     27     scanf("%d%d",&n,&m);
     28     for (i=1;i<=n;i++)
     29         scanf("%d%d",&a[i].x,&a[i].y);
     30     for (i=1;i<=m;i++)
     31         scanf("%d%d",&a[n+i].x,&a[n+i].y);
     32 
     33     ///can decrease
     34     int tp=n+m;
     35     for (i=1;i<=tp;i++)
     36         for (j=1;j<=tp;j++)
     37             dist[i][j]=abs(a[i].x-a[j].x) + abs(a[i].y-a[j].y);
     38 
     39     l=0,r=4000;///
     40     while (l<=r)
     41     {
     42         mid=(l+r)>>1;
     43 
     44         g=0;
     45         memset(use,0,sizeof(use));
     46         for (i=1;i<=n;i++)
     47             if (!use[i])
     48             {
     49                 memset(vis,0,sizeof(vis));
     50                 use[i]=1;
     51                 q[1]=i;
     52                 head=0,tail=1;
     53                 while (head<tail)
     54                 {
     55                     head++;
     56                     d=q[head];
     57                     for (j=1;j<=n;j++)
     58                         if (!use[j] && !vis[j] && dist[j][d]<=mid)
     59                         {
     60                             use[j]=1;
     61                             q[++tail]=j;
     62                         }
     63 
     64                     for (j=n+1;j<=tp;j++)
     65                         if (!vis[j] && dist[j][d]<=mid)
     66                             vis[j]=1,g++;
     67                 }
     68 
     69                 if (g!=m)
     70                     break;
     71             }
     72 
     73         if (i==n+1)
     74             r=mid-1;
     75         else
     76             l=mid+1;
     77     }
     78     sum1=l;
     79 
     80 
     81     mid=sum1+1;
     82 
     83     g=0;
     84     memset(use,0,sizeof(use));
     85     for (i=n+1;i<=tp;i++)
     86         if (!use[i])
     87         {
     88             memset(vis,0,sizeof(vis));
     89             use[i]=1;
     90             q[1]=i;
     91             head=0,tail=1;
     92             while (head<tail)
     93             {
     94                 head++;
     95                 d=q[head];
     96                 for (j=n+1;j<=tp;j++)
     97                     if (!use[j] && !vis[j] && dist[j][d]<=mid)
     98                     {
     99                         use[j]=1;
    100                         q[++tail]=j;
    101                     }
    102 
    103                 for (j=1;j<=n;j++)
    104                     if (!vis[j] && dist[j][d]<=mid)
    105                         vis[j]=1,g++;
    106             }
    107 
    108             if (g!=n)
    109                 break;
    110         }
    111 
    112 
    113     if (i!=tp+1)
    114         printf("1");
    115     else
    116         printf("0");
    117     return 0;
    118 }
    119 /*
    120 1 1
    121 2 3
    122 4 5
    123 
    124 2 1
    125 0 0
    126 2 0
    127 3 0
    128 
    129 2 1
    130 0 0
    131 2 0
    132 4 0
    133 */

    FMesh

    easy&funny problem

    “对一个问题设置解决方案” 类题目

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10  
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=1e9+7;
    14 const int maxn=5e5+10;
    15  
    16 /*
    17 add 3*3 is also ok
    18 so 2*3,3*2,3*3 在场上最多出现一次
    19 设置之前矩阵的放置位置,使可以放置而不重叠,然后进行消除
    20 */
    21  
    22 char str[maxn];
    23  
    24 int cond[4];
    25  
    26 int f[8][2]={
    27 4,1,
    28 4,4,
    29 5,1,
    30 5,4,
    31 1,5,
    32 4,5,
    33 1,4,
    34 4,4
    35 };
    36  
    37 int main()
    38 {
    39     int n,i,j,k;
    40     scanf("%s",str);
    41     n=strlen(str);
    42     for (i=0;i<n;i++)
    43     {
    44         j=str[i]-48;
    45         k=(j<<1)|cond[j];
    46         printf("%d %d
    ",f[k][0],f[k][1]);
    47         cond[j]^=1;
    48     }
    49     return 0;
    50 }

    GMath

    看求解过程

    1.dp

    2.

    (不太清楚理解正不正确)

    A.系数是确定的

    多项式(N<=30)^M(N<=1e9)

    多项式快速幂 log(NlogN)

    多项式乘积的结果与初始矩阵相乘
    多项式乘法 FFT log(NlogN)


    ---------------

    dp优化

    目标是使得sin(kx)变为若干个sin(yi)的运算,其中yi<kx。

    at last

      (from PPT solution)

    sin(k1*x)*sin(k2*X)*..*...*sin(km-1*X)*sin((K-1)X) : tot=N-1

    sin(k1*x)*sin(k2*X)*..*...*sin(km-1*X)*sin((K-2)X) : tot=N-2

    so

    (from PPT solution)

    (from PPT solution)

    N-1 -> N 系数固定,可用快速幂

    (2M)^3 * log(N) * T

    1.结构体 数组 must initialize for mat z(variable is not a constant)

    2.快速幂 可写在main函数里,初始的y,可赋值

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-12;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=1e5+10;
     15 const int maxm=60+10;
     16 
     17 int mm;
     18 double v[maxm];
     19 
     20 struct mat
     21 {
     22     double a[maxm][maxm];
     23     mat()
     24     {
     25         memset(a,0,sizeof(a));  ///must initialize for mat z(variable is not a constant)
     26     }
     27     void init()
     28     {
     29         int i;
     30         memset(a,0,sizeof(a));
     31         for (i=1;i<=mm;i++)
     32             a[i][i]=1;
     33     }
     34     mat operator*(const mat &y) const
     35     {
     36         mat z;
     37         int i,j,k;
     38         for (k=1;k<=mm;k++)
     39             for (i=1;i<=mm;i++)
     40                 for (j=1;j<=mm;j++)
     41                     z.a[i][j]+=a[i][k]*y.a[k][j];
     42         return z;
     43     }
     44 }mat0,mat1;
     45 
     46 mat mul(mat a,int b)
     47 {
     48     mat y;
     49     y.init();
     50     while (b)
     51     {
     52         if (b&1)
     53             y=y*a;
     54         a=a*a;
     55         b>>=1;
     56     }
     57     return y;
     58 }
     59 
     60 
     61 int main()
     62 {
     63     int t,m,M,n,i,j;
     64     double x,tot;
     65     mat mat0,mat1;
     66     scanf("%d",&t);
     67     m=30,mm=60;
     68     while (t--)
     69     {
     70         scanf("%d%d%lf",&M,&n,&x);
     71 //        mm=m<<1;
     72         ///写成30,60:避免覆盖 当n=1,2时 (v[1],v[2],v[m+1])
     73         ///i=1..m F[N-1][i] ; j=(i=1..n)+m F[N-2][i]
     74         ///F[N]
     75         memset(mat0.a,0,sizeof(mat0.a));
     76         for (i=1;i<=m;i++)
     77         {
     78             mat0.a[i][i]=cos(x)*2;
     79             mat0.a[i][i+m]=-1;
     80             ///注意 mat0.a[p][q] * v[q] [...][p]使用[...][q]
     81             if (i!=1)
     82                 mat0.a[i][i-1]=sin(x);
     83         }
     84         ///F[N-1]
     85         for (i=m+1;i<=mm;i++)
     86             mat0.a[i][i-m]=1;
     87         ///F[2]
     88         memset(v,0,sizeof(v));
     89         v[1]=sin(x*2);
     90         v[2]=sin(x)*sin(x);
     91         ///F[1]
     92         v[m+1]=sin(x);
     93 //        v[1]=sin(x);
     94 //        for (i=1;i<=m;i++)
     95 //            v[i]=i;
     96 //        ///F[0]
     97 //        for (i=m+1;i<=mm;i++)
     98 //            v[i]=0;
     99 
    100         ///F[n+1] F[n]
    101         mat1=mul(mat0,n-1);
    102 //        mat1=mul(mat0,n);
    103         tot=0;
    104         ///F[n] right part
    105         for (j=1;j<=mm;j++)
    106             tot+=mat1.a[m+M][j]*v[j];
    107 
    108         ///另外的写法:初始的矩阵y(in mul function)=v,快速幂直接在main函数内写
    109 
    110         if (!(fabs(tot)>eps && tot<0))
    111             printf("+");
    112         else
    113         {
    114             printf("-");
    115             tot=-tot;
    116         }
    117         while (tot<1)
    118             tot*=10;
    119         while (tot>=10)
    120             tot/=10;
    121         printf("%d
    ",(int)tot);
    122     }
    123     return 0;
    124 }
    125 /*
    126 4
    127 1 1 1
    128 2 2 1
    129 3 3 1
    130 4 4 1
    131 sin(1)=0.84147
    132 ‭0.8414709848078965066525023216303‬
    133 ‭0.70807341827357119349878411475038‬
    134 ‭0.595821144644523‬
    135 ‭0.50136796566561970416888809186316‬
    136 
    137 2
    138 1 0 1
    139 2 0 1
    140 */

    HModify

    一个点能到达的点中最小的属性

    tarjan[每个互相能访问的集合]+缩点[一个集合能访问另外哪些集合,无环]

    建树 给每个字符串赋予编号 or 使用hash

    然后方法有点绕了。

    -------------------------

    题解的方法:

    反边,排序。

    修改的代价从小到大,该方案能到达的所有字符串(还没被处理)选择该方案(也就是当前代价最小的方案)。

    学习了!

    代码1

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=1e9+7;
     14 const int maxn=3e5+10;
     15 const int maxm=5e5+10;
     16  
     17 struct node
     18 {
     19     int d;
     20     node *to;
     21 }*e[maxn];
     22  
     23 struct rec
     24 {
     25     int num;
     26     rec *nex[26];
     27 }*tr;
     28  
     29 struct word
     30 {
     31     ll x,y;
     32 }value[maxn],va,group_value[maxn];
     33  
     34 int num,ind,low[maxn],dfn[maxn],st[maxn],cnt_st,cnt_group,group[maxn],b[maxn];
     35 bool vis[maxn],vis_st[maxn];
     36  
     37 char str[maxm];
     38  
     39 word min(word a,word b)
     40 {
     41     if (a.x==b.x)
     42         return a.y<b.y?a:b;
     43     return a.x<b.x?a:b;
     44 }
     45  
     46 int build()
     47 {
     48     rec *pos,*p;
     49     int len,d,i,x=0;
     50     scanf("%s",str);
     51     len=strlen(str);
     52  
     53     pos=tr;
     54     for (i=0;i<len;i++)
     55     {
     56         d=str[i]-97;
     57         if (!pos->nex[d])
     58         {
     59             p=new rec();
     60             pos->nex[d]=p;
     61         }
     62         pos=pos->nex[d];
     63     }
     64     if (!pos->num)
     65     {
     66         pos->num=++num;
     67         for (i=0;i<len;i++)
     68             if (str[i]=='a' || str[i]=='e' || str[i]=='i' || str[i]=='o' || str[i]=='u')
     69                 x++;
     70         value[num]={x,len};
     71     }
     72     return pos->num;
     73 }
     74  
     75 void tarjan(int d)
     76 {
     77     dfn[d]=low[d]=++ind;
     78     st[++cnt_st]=d;
     79     vis[d]=1;
     80     node *p=e[d];
     81     int dd;
     82     while (p)
     83     {
     84         dd=p->d;
     85         if (!vis[dd])
     86         {
     87             tarjan(dd);
     88             low[d]=min(low[d],low[dd]);
     89         }
     90         else if (!vis_st[dd])
     91             low[d]=min(low[d],dfn[dd]);
     92         p=p->to;
     93     }
     94     if (dfn[d]==low[d])
     95     {
     96         cnt_group++;
     97         va={inf,inf};
     98         while (st[cnt_st]!=d)
     99         {
    100             va=min(va,value[st[cnt_st]]);
    101             vis_st[st[cnt_st]]=1;
    102             group[st[cnt_st--]]=cnt_group;
    103         }
    104         va=min(va,value[st[cnt_st]]);
    105         vis_st[st[cnt_st]]=1;
    106         group[st[cnt_st--]]=cnt_group;
    107         group_value[cnt_group]=va;
    108     }
    109 }
    110  
    111 void dfs(int d)
    112 {
    113     node *p=e[d];
    114     int dd;
    115     vis[d]=1;
    116     while (p)
    117     {
    118         dd=p->d;
    119         if (!vis[dd])
    120             dfs(dd);
    121         group_value[group[d]]=min(group_value[group[d]],group_value[group[dd]]);
    122         p=p->to;
    123     }
    124 }
    125  
    126 int main()
    127 {
    128     node *p;
    129     int n,m,i,x,y;
    130     ll totx,toty;
    131     tr=new rec();
    132     scanf("%d",&n);
    133     for (i=1;i<=n;i++)
    134     {
    135         x=build();
    136         b[i]=x;///有可能重复
    137     }
    138  
    139     scanf("%d",&m);
    140     for (i=1;i<=m;i++)
    141     {
    142         x=build();
    143         y=build();
    144         p=new node();
    145         p->d=y;
    146         p->to=e[x];
    147         e[x]=p;
    148     }
    149  
    150     for (i=1;i<=num;i++)
    151         if (!vis[i])
    152             tarjan(i);
    153  
    154     memset(vis,0,sizeof(vis));
    155     for (i=1;i<=num;i++)
    156         if (!vis[i])
    157             dfs(i);
    158  
    159     totx=0,toty=0;
    160     for (i=1;i<=n;i++)
    161         totx+=group_value[group[b[i]]].x , toty+=group_value[group[b[i]]].y;
    162     printf("%lld %lld",totx,toty);
    163     return 0;
    164 }
    165 /*
    166 3
    167 a b c
    168 3
    169 a i
    170 b a
    171 c a
    172  
    173 4
    174 a e i e
    175 3
    176 a e
    177 e i
    178 i a
    179  
    180  
    181 4
    182 a a aaa aaaa
    183 4
    184 a aaaa
    185 aaaa aaa
    186 aaa aa
    187 aa aaaa
    188  
    189  
    190 5
    191 b a e i u
    192 6
    193 a e
    194 e i
    195 i a
    196 i u
    197 u b
    198 b u
    199 */

    代码2

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <map>
     11 
     12 const double eps=1e-8;
     13 const ll inf=1e9;
     14 const ll mod=1e9+7;
     15 const int maxn=3e5+10;  ///larger
     16 const int maxlen=5e5+10;
     17 
     18 ll chu[5]={998244353,469762049,167772161,10000019,10000079};
     19 ll cnt_chu=5,value[5];
     20 char str[maxlen];
     21 int id=0;
     22 
     23 struct node
     24 {
     25     ll v[5];
     26     ll vx,vy;
     27     ///同时也是map的排序方法
     28     bool operator<(const node &b) const
     29     {
     30         if (vx<b.vx)
     31             return 0;
     32         else if (vx>b.vx)
     33             return 1;
     34         if (vy<b.vy)
     35             return 0;
     36         else if (vy>b.vy)
     37             return 1;
     38         for (int i=0;i<5;i++)
     39             if (v[i]<b.v[i])
     40                 return 0;
     41             else if (v[i]>b.v[i])
     42                 return 1;
     43         return 0;///actually won't work
     44     }
     45     bool operator<<(const node &b) const
     46     {
     47         if (vx==b.vx)
     48             return vy<b.vy;
     49         return vx<b.vx;
     50     }
     51     node operator+(const node &b) const
     52     {
     53         node z;
     54         z.vx=vx+b.vx;
     55         z.vy=vy+b.vy;
     56         return z;
     57     }
     58 }ask[maxn],cost[maxn];
     59 
     60 map<node,int> num;
     61 
     62 struct rec
     63 {
     64     node x,y;
     65     bool operator<(const rec &b) const
     66     {
     67         return y<<b.y;///
     68     }
     69 }rule[maxn];
     70 
     71 struct point
     72 {
     73     int d;
     74     point* to;
     75 }*e[maxn];
     76 
     77 int q[maxn];
     78 bool vis[maxn];
     79 
     80 void work(node &z)
     81 {
     82     int len,j,k,vx=0;
     83     scanf("%s",str);
     84     len=strlen(str);
     85 
     86     for (k=0;k<cnt_chu;k++)
     87     {
     88         value[k]=0;
     89         ///'a':1 *27
     90         for (j=0;j<len;j++)
     91             value[k]=(value[k]*27+str[j]-97+1)%chu[k];
     92     }
     93     for (j=0;j<len;j++)
     94         if (str[j]=='a' || str[j]=='e' || str[j]=='i' || str[j]=='o' || str[j]=='u')
     95             vx++;
     96     z.vx=vx;
     97     z.vy=len;
     98     for (j=0;j<cnt_chu;j++)
     99         z.v[j]=value[j];
    100 
    101     if (num.find(z)==num.end())
    102     {
    103         num[z]=++id;
    104         cost[id]=z;
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     point *p;
    111     node r;
    112     int n,m,i,j,x,y,head,tail,d;
    113     scanf("%d",&n);
    114     for (i=1;i<=n;i++)
    115         work(ask[i]);
    116 
    117     scanf("%d",&m);
    118     for (i=1;i<=m;i++)
    119     {
    120         work(rule[i].x);
    121         work(rule[i].y);
    122         ///反边 通过访问,一个字符串可以到达的所有字符串
    123         x=num[rule[i].x];
    124         y=num[rule[i].y];
    125         if (x!=y)
    126         {
    127             p=new point();
    128             p->d=x;
    129             p->to=e[y];
    130             e[y]=p;
    131         }
    132     }
    133     sort(rule+1,rule+m+1);
    134     for (i=1;i<=m;i++)
    135         if (!vis[num[rule[i].y]])
    136         {
    137             vis[num[rule[i].y]]=1;
    138             head=0,tail=1;
    139             q[1]=num[rule[i].y];
    140             while (head<tail)
    141             {
    142                 head++;
    143                 d=q[head];
    144                 p=e[d];
    145                 while (p)
    146                 {
    147                     if (!vis[p->d])
    148                     {
    149                         q[++tail]=p->d;
    150                         vis[p->d]=1;
    151                     }
    152                     p=p->to;
    153                 }
    154             }
    155             for (j=1;j<=tail;j++)
    156                 if (rule[i].y<<cost[q[j]])///
    157                     cost[q[j]]=rule[i].y;
    158         }
    159 
    160     r.vx=0,r.vy=0;
    161     for (i=1;i<=n;i++)
    162         if (ask[i]<<cost[num[ask[i]]])///
    163             r=r+ask[i];
    164         else
    165             r=r+cost[num[ask[i]]];
    166 
    167     printf("%lld %lld",r.vx,r.vy);
    168     return 0;
    169 }
    170 /*
    171 3 a a a
    172 1
    173 a a
    174 
    175 1
    176 aaa
    177 1
    178 bbb aaa
    179 
    180 1
    181 aaab
    182 2
    183 aaab aaaaab
    184 aaaaab aabb
    185 
    186 
    187 1
    188 aaab
    189 2
    190 aaaaab aabb
    191 aaab aaaaab
    192 
    193 
    194 1
    195 ab
    196 3
    197 ab aab
    198 aab aaab
    199 aaab bbbbbbbbbbbbb
    200 
    201 202 1 aaa
    203 2
    204 aaa aaa
    205 aaa aaa
    206 
    207 
    208 
    209 4
    210 ab ab aab aaaa
    211 3
    212 ab aab
    213 aab aaab
    214 aaab bbbbbbbbbbbbb
    215 
    216 1
    217 a
    218 1
    219 aa bb
    220 
    221 
    222 1
    223 aaaa
    224 0
    225 
    226 1
    227 aaaa
    228 1
    229 aaaa aaaaa
    230 
    231 1
    232 aaaa
    233 1
    234 aaaa aaa
    235 
    236 2
    237 a b
    238 2
    239 a b
    240 b a
    241 
    242 3
    243 a e i
    244 3
    245 a e
    246 e i
    247 i a
    248 
    249 */
    250 /*
    251 如果结构体'<'写错了
    252 两个不同/相同的结构体被认为是相同/不同的结构体
    253 https://www.cnblogs.com/cmyg/p/11252867.html
    254 
    255 每个数依次输出编号
    256 num=1
    257 num=2
    258 num=3
    259 num=4
    260 num=3
    261 num=4
    262 num=5
    263 num=6
    264 num=7
    265 num=3
    266 num=4
    267 num=8
    268 num=9
    269 num=10
    270 num=11
    271 
    272 500
    273 aaavakaumfjbaujybvgapjxlis eawsmkalasfa d o l
    274 */

    IMatrix Again

    f(x) 递增 /  0/1不能/能实现,则为0 0 0 0... 0 1 1 ... 1

    求最小数值:二分

    求若干个a*b的矩阵的属性

    两个单调队列是常规操作

    如 https://www.cnblogs.com/cmyg/p/11205042.html E题

    第一次求出若干个a*1,

    第二次求出若干个a*b(由b个a*1组成)

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const int maxn=5e2+10;
     12 const double eps=1e-8;
     13 const ll inf=1e9;
     14  
     15 ///二维线段树是否可行
     16  
     17 int n,m,g;
     18 int a[maxn][maxn],x[maxn][maxn],y[maxn];
     19 int headx[maxn],tailx[maxn],heady,taily,vmax[maxn][maxn];
     20  
     21 bool work(int l)
     22 {
     23     int i,j;
     24  
     25     ///max
     26     for (j=1;j<=m;j++)
     27         headx[j]=1,tailx[j]=0;
     28  
     29     for (i=1;i<=n;i++)
     30     {
     31         heady=1,taily=0;
     32  
     33         for (j=1;j<=m;j++)
     34         {
     35             while (headx[j]<=tailx[j] && x[j][headx[j]]<=i-l)
     36                 headx[j]++;
     37             while (headx[j]<=tailx[j] && a[x[j][tailx[j]]][j]<=a[i][j])
     38                 tailx[j]--;
     39             x[j][++tailx[j]]=i;
     40  
     41             while (heady<=taily && y[heady]<=j-l)
     42                 heady++;
     43             while (heady<=taily && a[ x[y[taily]][headx[y[taily]]] ][y[taily]] <= a[ x[j][headx[j]] ][j])
     44                 taily--;
     45             y[++taily]=j;
     46  
     47             if (i>=l && j>=l)
     48                 vmax[i][j]=a[ x[y[heady]][headx[y[heady]]] ][y[heady]];
     49  
     50         }
     51     }
     52  
     53     ///min
     54     for (j=1;j<=m;j++)
     55         headx[j]=1,tailx[j]=0;
     56  
     57     for (i=1;i<=n;i++)
     58     {
     59         heady=1,taily=0;
     60  
     61         for (j=1;j<=m;j++)
     62         {
     63             while (headx[j]<=tailx[j] && x[j][headx[j]]<=i-l)
     64                 headx[j]++;
     65             while (headx[j]<=tailx[j] && a[x[j][tailx[j]]][j]>=a[i][j])
     66                 tailx[j]--;
     67             x[j][++tailx[j]]=i;
     68  
     69             while (heady<=taily && y[heady]<=j-l)
     70                 heady++;
     71             while (heady<=taily && a[ x[y[taily]][headx[y[taily]]] ][y[taily]] >= a[ x[j][headx[j]] ][j])
     72                 taily--;
     73             y[++taily]=j;
     74  
     75             if (i>=l && j>=l && vmax[i][j]-a[ x[y[heady]][headx[y[heady]]] ][y[heady]] <=g )
     76                 return 1;
     77  
     78         }
     79     }
     80  
     81     return 0;
     82 }
     83  
     84 int main()
     85 {
     86     int i,j,l,r,M;
     87     scanf("%d%d%d",&n,&m,&g);
     88     for (i=1;i<=n;i++)
     89         for (j=1;j<=m;j++)
     90             scanf("%d",&a[i][j]);
     91     l=1,r=min(n,m);
     92     while (l<=r)
     93     {
     94         M=(l+r)>>1;
     95         if (work(M))
     96             l=M+1;
     97         else
     98             r=M-1;
     99     }
    100     printf("%d",r);
    101     return 0;
    102 }

    JMex

    对数字进行排序

    证明:

    a1,...,ak 能表示 1~x

    对于a_{k+1}

    若a_{k+1} > x+1,则不能表示的最小数为x+1

    若a_{k+1} <= x+1

    则a_{k+1} 加上 1~x,能表示1 +a_{k+1} ~ x + a_{k+1}

    再包含集合1~x,即能表示1~x+a_{k+1}。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <queue>
    10 #include <bitset>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15   
    16 #define ll long long
    17 const int maxn=1e5+10;
    18 const ll inf=1e9+7;
    19 const double eps=1e-8;
    20   
    21 ll a[maxn];
    22   
    23 int main()
    24 {
    25     int n,i;
    26     ll sum=0;
    27     scanf("%d",&n);
    28     for (i=1;i<=n;i++)
    29         scanf("%lld",&a[i]);
    30     sort(a+1,a+n+1);
    31     sum=0;
    32     for (i=1;i<=n;i++)
    33     {
    34         if (a[i]>sum+1)
    35         {
    36             printf("%lld",sum+1);
    37             break;
    38         }
    39         sum+=a[i];
    40     }
    41     if (i==n+1)
    42         printf("%lld",sum+1);
    43     return 0;
    44 }

    KMoney

    费用流

    设置连边/边值是常规操作

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10  
     11 const double eps=1e-8;
     12 const ll inf=1e18;
     13 const ll mod=1e9+7;
     14 const int maxn=1e2+10;///*2 point
     15  
     16 ll flow,fee;
     17  
     18 struct node
     19 {
     20     ll d,len,cost;
     21     node *to,*opp;
     22 }*e[maxn],*pre[maxn];
     23  
     24 int ss,tt;
     25 ll dis[maxn][maxn],dist[maxn],add[maxn];
     26 int g[maxn],l[maxn],r[maxn],q[maxn];
     27 bool vis[maxn];
     28  
     29 void addedge(int a,int b,ll c,ll d)
     30 {
     31     node *p,*q;
     32     p=new node();
     33     q=new node();
     34     p->d=b;
     35     p->len=c;
     36     p->cost=d;
     37     p->opp=q;
     38     p->to=e[a];
     39     e[a]=p;
     40  
     41     q->d=a;
     42     q->len=0;
     43     q->cost=-d;
     44     q->opp=p;
     45     q->to=e[b];
     46     e[b]=q;
     47 }
     48  
     49 void bfs()
     50 {
     51     node *p;
     52     int head,tail,d,dd;
     53     while (1)
     54     {
     55         memset(vis,0,sizeof(vis));
     56         memset(dist,0x7f,sizeof(dist));
     57         dist[ss]=0;
     58         add[ss]=inf;
     59         head=0,tail=1;
     60         q[1]=ss,vis[ss]=1;
     61         while (head!=tail)
     62         {
     63             head=(head+1)%maxn;
     64             d=q[head];
     65             p=e[d];
     66             while (p)
     67             {
     68                 dd=p->d;
     69                 if (p->len && dist[dd]>dist[d]+p->cost)
     70                 {
     71                     add[dd]=min(add[d],p->len);
     72                     dist[dd]=dist[d]+p->cost;
     73                     pre[dd]=p->opp;
     74                     if (!vis[dd])
     75                     {
     76                         tail=(tail+1)%maxn;
     77                         q[tail]=dd;
     78                         vis[dd]=1;
     79                     }
     80                 }
     81                 p=p->to;
     82             }
     83             vis[d]=0;
     84         }
     85         if (dist[tt]==dist[maxn-1])
     86             return;
     87  
     88         flow+=add[tt];
     89         fee+=add[tt]*dist[tt];
     90         d=tt;
     91 //        printf("add=%lld dist=%lld
    ",add[tt],dist[tt]);
     92         while (d!=ss)
     93         {
     94 //            printf("%d ",d);
     95             pre[d]->len+=add[tt];
     96             pre[d]->opp->len-=add[tt];
     97             d=pre[d]->d;
     98         }
     99 //        printf("
    ");
    100     }
    101 }
    102  
    103 int main()
    104 {
    105     int n,m,k,a,b,c,i,j,price;
    106     scanf("%d%d",&n,&m);
    107     ss=0,tt=2*n+1;
    108     for (i=1;i<=n;i++)
    109     {
    110         scanf("%d%d%d%lld",&l[i],&r[i],&g[i],&price);
    111         addedge(ss,i,inf,price);
    112         addedge(i,tt,g[i],0);
    113         addedge(0,i+n,g[i],0);
    114     }
    115  
    116     for (i=1;i<=n;i++)
    117         for (j=1;j<=n;j++)
    118             if (i!=j)
    119                 dis[i][j]=inf;
    120     while (m--)
    121     {
    122         scanf("%d%d%d",&a,&b,&c);
    123         dis[a][b]=dis[b][a]=c;
    124     }
    125  
    126     for (k=1;k<=n;k++)
    127         for (i=1;i<=n;i++)
    128             for (j=1;j<=n;j++)
    129                 if (dis[i][j]>dis[i][k]+dis[k][j])
    130                     dis[i][j]=dis[i][k]+dis[k][j];
    131     ///i->j
    132     for (i=1;i<=n;i++)
    133         for (j=1;j<=n;j++)
    134             if (i!=j && dis[i][j]!=inf && r[i]<l[j])
    135                 addedge(i+n,j,g[i],dis[i][j]);
    136  
    137     bfs();
    138     printf("%lld",fee);
    139     return 0;
    140 }
  • 相关阅读:
    POJ 1236 Network of Schools(tarjan算法 + LCA)
    Hrbustoj 2266 Legendary Weights(辗转相除求最大公约数)
    纯虚函数的学习和使用
    完全背包(内含不能恰好装满的情况)
    多重背包并判断能否装满(附01完全背包思想)
    UVA 796 Critical Links (tarjan算法求割边)
    poj 2594 Treasure Exploration(最小路径覆盖,可重点)
    poj 3020 Antenna Placement (最小路径覆盖)
    ZOJ 1642
    Playground
  • 原文地址:https://www.cnblogs.com/cmyg/p/10747388.html
Copyright © 2011-2022 走看看