• Loj一本通刷题记录


    夏令营回来后就不知道怎么回事,状态一直不好==

    为了让自己不要太颓废,开个坑在noip前把一本通的好题都刷一遍。

    如果想要noip拿省一的话,就要开始好好努力了。加油!

    为了节省时间,一些比较简单的东西就不再赘述了。

    第一部分 基础算法

    第 1 章 贪心算法

    #10000 「一本通 1.1 例 1」活动安排

    按右端点排序。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long 
     9 #define ull unsigned long long
    10 #define out(a) printf("%d ",a)
    11 #define writeln printf("
    ")
    12 const int N=1e5+50;
    13 using namespace std;
    14 typedef int array[N];
    15 int n;
    16 int now=0,ans=0;
    17 int read()
    18 {
    19     int s=0,t=1; char c;
    20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    22     return s*t;
    23 }
    24 ll readl()
    25 {
    26     ll s=0,t=1; char c;
    27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    29     return s*t;
    30 }
    31 struct node
    32 {
    33     int l,r;
    34 }a[N];
    35 bool cmp(node a,node b)
    36 {
    37     return a.r==b.r?a.l<b.l:a.r<b.r;
    38 }
    39 int main()
    40 {
    41     n=read();
    42     for (int i=1;i<=n;i++)
    43       a[i].l=read(),a[i].r=read();
    44     sort(a+1,a+n+1,cmp); 
    45     for (int i=1;i<=n;i++)
    46       if (now<=a[i].l) now=a[i].r,ans++;
    47     out(ans);
    48     return 0;
    49 }
    View Code

    #10001 「一本通 1.1 例 2」种树

    按右端点排序,在区间的末尾种树,若当前区间前面一部分种了一些,在区间末尾补上足够数量。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n,h;
    15 int cnt=0,ans=0;
    16 bool vis[N];
    17 struct node
    18 {
    19     int l,r,t;
    20 }a[N];
    21 int read()
    22 {
    23     int s=0,t=1; char c;
    24     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    25     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    26     return s*t;
    27 }
    28 ll readl()
    29 {
    30     ll s=0,t=1; char c;
    31     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    32     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    33     return s*t;
    34 }
    35 bool cmp(node a,node b)
    36 {
    37     return a.r==b.r?a.l<b.l:a.r<b.r;
    38 }
    39 int main()
    40 {
    41     n=read();
    42     h=read();
    43     for (int i=1;i<=h;i++)
    44       a[i].l=read(),a[i].r=read(),a[i].t=read();
    45     memset(vis,false,sizeof(vis));
    46     sort(a+1,a+h+1,cmp); 
    47     for (int i=1;i<=h;i++){
    48       cnt=0;
    49       for (int j=a[i].l;j<=a[i].r;j++)
    50         if (vis[j]) cnt++;
    51         if (cnt>=a[i].t) continue;
    52       for (int j=a[i].r;j>=a[i].l;j--){
    53         if (!vis[j]) {
    54           vis[j]=true;
    55           ans++; cnt++;
    56           if (cnt>=a[i].t) break;
    57           }
    58         }
    59     }
    60       out(ans);
    61     return 0;
    62 }
    View Code

    #10005 「一本通 1.1 练习 1」数列极差

    开一个大根堆和一个小根堆维护一下。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n,x;
    15 int a,b;
    16 priority_queue<int>q_mi;
    17 priority_queue<int,vector<int>,greater<int> >q_mx;
    18 int read()
    19 {
    20     int s=0,t=1; char c;
    21     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    22     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    23     return s*t;
    24 }
    25 ll readl()
    26 {
    27     ll s=0,t=1; char c;
    28     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    29     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    30     return s*t;
    31 }
    32 int main()
    33 {
    34     n=read();
    35     for (int i=1;i<=n+1;i++){
    36       x=read();
    37       if (i>n) break;
    38       q_mx.push(x),q_mi.push(x);
    39     }
    40     while (q_mx.size()>1){
    41       a=q_mx.top(); q_mx.pop(); 
    42       b=q_mx.top(); q_mx.pop();
    43       q_mx.push(a*b+1);
    44     }
    45     while (q_mi.size()>1){
    46       a=q_mi.top(); q_mi.pop(); 
    47       b=q_mi.top(); q_mi.pop();
    48       q_mi.push(a*b+1);
    49     }
    50     out(q_mx.top()-q_mi.top());
    51     return 0;
    52 }
    View Code

    #10006 「一本通 1.1 练习 2」数列分段

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n,m,x;
    15 int sum=0,ans=0;
    16 int read()
    17 {
    18     int s=0,t=1; char c;
    19     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    20     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    21     return s*t;
    22 }
    23 ll readl()
    24 {
    25     ll s=0,t=1; char c;
    26     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    27     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    28     return s*t;
    29 }
    30 int main()
    31 {
    32     n=read(); m=read(); sum=0; ans=1;
    33     for (int i=1;i<=n;i++){
    34       x=read();
    35       if (sum+x>m) ans++,sum=x;
    36       else sum+=x;
    37     }
    38     out(ans);
    39     return 0;
    40 }
    View Code

    #10007 「一本通 1.1 练习 3」线段

    经典题。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n,m,x;
    15 int now=0,ans=0;
    16 struct node
    17 {
    18     int l,r;
    19 }a[N];
    20 int read()
    21 {
    22     int s=0,t=1; char c;
    23     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    24     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    25     return s*t;
    26 }
    27 ll readl()
    28 {
    29     ll s=0,t=1; char c;
    30     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    31     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    32     return s*t;
    33 }
    34 bool cmp(node a,node b)
    35 {
    36     return a.r<b.r;
    37 }
    38 int main()
    39 {
    40     n=read();
    41     for (int i=1;i<=n;i++)
    42       a[i].l=read(),a[i].r=read();
    43     sort(a+1,a+n+1,cmp);
    44     ans=1; now=a[1].r;
    45     for (int i=2;i<=n;i++)
    46       if (a[i].l>=now) now=a[i].r,ans++;
    47     out(ans);
    48     return 0;
    49 }
    View Code

    #10008 「一本通 1.1 练习 4」家庭作业

    显然每个时刻只能写至多一个作业,那么我们枚举时间,将符合时间限制的作业放到一个大根堆里维护并选价值最大的那个出堆并计算答案,注意时间要倒着枚举否则一些时间限制到了的作业也会被重复计算,还有要注意元素是否会重复入队。。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n;
    15 int mx;
    16 int now=1;
    17 int ans=0;
    18 bool vis[N];
    19 priority_queue<int>q;
    20 struct node
    21 {
    22     int x,y;
    23 }a[N];
    24 int read()
    25 {
    26     int s=0,t=1; char c;
    27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    29     return s*t;
    30 }
    31 ll readl()
    32 {
    33     ll s=0,t=1; char c;
    34     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    35     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    36     return s*t;
    37 }
    38 bool cmp(node a,node b)
    39 {
    40     return a.x>b.x;
    41 }
    42 int main()
    43 {
    44     n=read();
    45     memset(vis,false,sizeof(vis));
    46     for (int i=1;i<=n;i++)
    47       a[i].x=read(),a[i].y=read(),mx=max(mx,a[i].x);
    48     sort(a+1,a+n+1,cmp); now=1;
    49     for (int i=mx;i;i--){  
    50       for (int j=now;j<=n;j++)
    51         if (a[j].x>=i&&!vis[j]) q.push(a[j].y),vis[j]=true;
    52         else {
    53           now=j; break;
    54           }
    55           if (!q.empty()) ans+=q.top(),q.pop();
    56     }
    57     out(ans);
    58     return 0;
    59 }
    View Code

     #10009. 「一本通 1.1 练习 5」钓鱼

    这题思路有点奇妙,想不出来于是翻了题解。。

    我们不妨假设他最远走到第i个位置,那么走路的花费就确定了,显然他不会走回头路,否则就不是最优解。

    那么我们考虑剩下的时间能钓多少鱼,用一个堆维护一下1到i的最优值就行了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int mod=1e9+7;
    13 using namespace std;
    14 int n,h,ho;
    15 int num[N],t[N],d[N];
    16 int sum=0,ans;
    17 struct node
    18 {
    19     int num,id;
    20     bool operator<(node a)const{
    21       return a.num>num;
    22     }
    23 }p;
    24 priority_queue<node>q;
    25 int read()
    26 {
    27     int s=0,t=1; char c;
    28     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    29     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    30     return s*t;
    31 }
    32 ll readl()
    33 {
    34     ll s=0,t=1; char c;
    35     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    36     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    37     return s*t;
    38 }
    39 int main()
    40 {
    41     n=read(),h=read(); h*=12; ho=h;
    42     for (int i=1;i<=n;i++)
    43       num[i]=read();
    44     for (int i=1;i<=n;i++)
    45       d[i]=read();
    46     for (int i=1;i<n;i++)
    47       t[i]=read(),t[i]+=t[i-1];
    48     ans=-23333333;
    49     for (int i=1;i<=n;i++){
    50       h=ho; h-=t[i-1]; sum=0;
    51       //out(h); writeln;
    52       while (!q.empty()) q.pop();
    53       for (int j=1;j<=i;j++)
    54         q.push((node){num[j],j});
    55        for (int j=1;j<=h;j++){
    56          p=q.top();
    57          if (p.num>0) {
    58           sum+=p.num;
    59           p.num-=d[p.id];
    60         }
    61          else p.num=0;
    62          q.pop();
    63          q.push(p);
    64        }
    65        ans=max(ans,sum);
    66      }
    67      out(ans);
    68      return 0;
    69 }
    View Code

    第 2 章 二分与三分

    #10011. 「一本通 1.2 例 1」愤怒的牛

     

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #include <stack>
     9 #define ll long long
    10 #define out(a) printf("%d",a)
    11 #define writeln printf("
    ")
    12 using namespace std;
    13 const int N=1e5+50;
    14 int n,m;
    15 int l,r,mid;
    16 int a[N];
    17 int read()
    18 {
    19     int s=0,t=1; char c;
    20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    22     return s*t;
    23 }
    24 ll readl()
    25 {
    26     ll s=0,t=1; char c;
    27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    29     return s*t;
    30 }
    31 bool check(int x)
    32 {
    33     int now=a[1],cnt=0,num=0;
    34     for (int i=2;i<=n;i++){
    35       if (a[i]-now>=x) now=a[i],num++;
    36       else cnt++;
    37       if (num+1==m) break;
    38     }
    39     if (cnt+m>n) return false;
    40     return true;
    41 }
    42 int main()
    43 {
    44     n=read(),m=read();
    45     for (int i=1;i<=n;i++)
    46       a[i]=read();
    47     sort(a+1,a+n+1);
    48     l=1; r=a[n]-a[1];
    49     while (l<=r){
    50       mid=(l+r)>>1;
    51       if (check(mid)) l=mid+1;
    52       else r=mid-1;
    53       //out(mid); writeln;
    54     }
    55     out(r);
    56     return 0;
    57 }
    View Code

     抱歉!NOIP后有些弃疗了,now i am back! 1.26 21:41

    #10015. 「一本通 1.2 练习 2」扩散

    给你几个点,单位时间内每个点都向四周扩散,问最快多久连到一块。

    没思路,看题解。

    如题,二分一下答案,然后很显然每个时刻对于两个点都相向扩散,所以判断条件是两倍的时间≥距离,就可以连一块。

    暴力枚举俩点,如果在时间内能相连就用并查集并一块,最后看一下是不是所有点都是同个祖先。

    注意距离是双向的!

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <queue>
     6 #include <cmath>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d ",a)
    10 #define ln printf("
    ")
    11 const int N=1e5+5;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int n;
    15 int x[N],y[N];
    16 int dis[150][150];
    17 int pre[N];
    18 int l,r,mid;
    19 int read()
    20 {
    21     int s=0,t=1; char c=getchar();
    22     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    23     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    24     return s*t;
    25 }
    26 ll readl()
    27 {
    28     ll s=0,t=1; char c=getchar();
    29     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    30     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    31     return s*t;
    32 }
    33 int find(int x)
    34 {
    35     return pre[x]==x?x:pre[x]=find(pre[x]);
    36 }
    37 void merge(int x,int y)
    38 {
    39     int fx,fy;
    40     fx=find(x); fy=find(y);
    41     if (fx!=fy) pre[fx]=fy;
    42 }
    43 bool check(int x)
    44 {
    45     int num=0;
    46     for (int i=1;i<=n;i++)
    47       pre[i]=i;
    48     for (int i=1;i<n;i++)
    49       for (int j=i+1;j<=n;j++)
    50         if (dis[i][j]<=(x<<1)) merge(i,j);
    51     for (int i=1;i<=n;i++)
    52       if (pre[i]==i) num++;
    53     return num==1;
    54 }
    55 int main()
    56 {
    57     n=read();
    58     for (int i=1;i<=n;i++)
    59       x[i]=read(),y[i]=read();
    60     for (int i=1;i<n;i++)
    61       for (int j=i+1;j<=n;j++)
    62         dis[i][j]=dis[j][i]=abs(x[i]-x[j])+abs(y[i]-y[j]);
    63     l=0; r=1e9;
    64     while (l<=r){
    65       mid=(l+r)>>1;
    66       if (check(mid)) r=mid-1;
    67       else l=mid+1;
    68     }
    69     out(l);
    70     return 0;
    71 }
    View Code

     

    第二部分 字符串算法

    第 1 章 哈希和哈希表

    讲道理很多哈希题写个map就能解决了=v=

    #103. 子串查找

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int MOD1=1e9+7;
    13 const int MOD2=19260817;
    14 using namespace std;
    15 int len1,len2;
    16 int num=0;
    17 int base;
    18 char s1[N],s2[N];
    19 ll Hash[N];
    20 ll pows[N];
    21 int ans=0;
    22 int read()
    23 {
    24     int s=0,t=1; char c;
    25     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    26     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    27     return s*t;
    28 }
    29 ll readl()
    30 {
    31     ll s=0,t=1; char c;
    32     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    33     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    34     return s*t;
    35 }
    36 ll get(int l,int r)
    37 {
    38     return (Hash[r]-(ll)Hash[l-1]*pows[r-l+1]%MOD1+MOD1)%MOD1;
    39 }
    40 void hashs(char s[])
    41 {
    42     ll res; char c;
    43     c='A';
    44     for (int i=0;i<len1;i++)
    45       Hash[i]=(Hash[i-1]*base+s[i]-c+1)%MOD1;
    46 }
    47 ll hash2(char s[])
    48 {
    49     ll res=0; char c;
    50     c='A';
    51     for (int i=0;i<len2;i++)
    52       res=(res*base+s[i]-c+1)%MOD1;
    53     return res;
    54 }
    55 int main()
    56 {
    57     scanf("%s",s1); 
    58     scanf("%s",s2); 
    59     base=131; pows[0]=1; len1=strlen(s1); len2=strlen(s2);
    60     for (int i=1;i<=len2;i++)
    61       pows[i]=pows[i-1]*base%MOD1;
    62     hashs(s1);
    63     num=hash2(s2); 
    64     for (int i=0;i<=len1-len2;i++)
    65       if (get(i,i+len2-1)==num) ans++;
    66     out(ans);
    67     return 0;
    68 }
    View Code

    #10034. 「一本通 2.1 例 2」图书管理

    偷懒写了个map。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int MOD1=1e9+7;
    13 const int MOD2=19260817;
    14 using namespace std;
    15 map<string,int>cnt;
    16 int n,len1,len2;
    17 int num=0;
    18 int base;
    19 char s1[N],s2[N];
    20 ll Hash[N];
    21 ll pows[N];
    22 int ans=0;
    23 int read()
    24 {
    25     int s=0,t=1; char c;
    26     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    27     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    28     return s*t;
    29 }
    30 ll readl()
    31 {
    32     ll s=0,t=1; char c;
    33     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    34     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    35     return s*t;
    36 }
    37 int main()
    38 {
    39     n=read();
    40     for (int i=1;i<=n;i++){
    41       scanf("%s",s1); gets(s2);
    42       if (s1[0]=='a') cnt[s2]++;
    43       else {
    44           if (cnt[s2]>0) puts("yes");
    45           else puts("no");
    46       }
    47     }
    48     return 0;
    49 }
    View Code

    #10035. 「一本通 2.1 练习 1」Power Strings

    枚举下每段的长度,显然要么长度小于等于len/2,要么等于len。

    然后算出每段hash值判断取最小即可。

    其实没必要用memset,用了反而会T掉QAQ

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d ",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int MOD=1e9+7;
    13 const int base=131;
    14 using namespace std;
    15 int len,mx,ans;
    16 ll Hash[N],Pow[N],last,num;
    17 char s[N];
    18 bool flag,f;
    19 int read()
    20 {
    21     int s=0,t=1; char c;
    22     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    23     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    24     return s*t;
    25 }
    26 ll readl()
    27 {
    28     ll s=0,t=1; char c;
    29     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    30     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    31     return s*t;
    32 }
    33 ll get(int l,int r)
    34 {
    35     return (Hash[r]-(ll)Hash[l-1]*Pow[r-l+1]%MOD+MOD)%MOD;
    36 }
    37 void hashs(char s[])
    38 {
    39     for (int i=0;i<len;i++)
    40       Hash[i]=(ll)(Hash[i-1]*base+s[i]-'A'+1)%MOD;
    41 }
    42 int main()
    43 {
    44     mx=0; Pow[0]=1;
    45     while (~scanf("%s",s)){
    46       //memset(Hash,0,sizeof(Hash));
    47       if (s[0]=='.') break;
    48       len=strlen(s); 
    49       if ((len>>1)>mx){
    50         for (int i=mx+1;i<=(len>>1);i++)
    51           Pow[i]=(ll)Pow[i-1]*base%MOD;
    52         mx=len>>1;
    53       }
    54       hashs(s); f=false; last=num=0;
    55       for (int i=1;i<=(len>>1);i++){
    56         if (len%i==0){
    57           flag=true;
    58           for (int j=0;j<len-i+1;j+=i){
    59               num=get(j,j+i-1);
    60               if (j==0){
    61                 last=num;
    62                 continue;
    63             }
    64             if (num!=last) {
    65               flag=false;
    66               break;
    67             }
    68           }
    69           if (flag) {
    70             ans=i,f=true;
    71             break;
    72           }
    73         }
    74       }
    75       if (f) out(len/ans);
    76       else out(1);
    77       writeln;
    78     }
    79     return 0;
    80 }
    81       
    View Code

     #10036. 「一本通 2.1 练习 2」Seek the Name, Seek the Fame

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll  long long
     9 #define out(a) printf("%d ",a)
    10 #define writeln printf("
    ")
    11 const int N=4e5+50;
    12 const int MOD=1e9+7;
    13 const int base=233;
    14 using namespace std;
    15 int len,mx,tot=0;
    16 char s[N];
    17 ll Hash[N],Pow[N];
    18 int ans[N];
    19 int read()
    20 {
    21     int s=0,t=1; char c;
    22     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    23     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    24     return s*t;
    25 }
    26 ll readl()
    27 {
    28     ll s=0,t=1; char c;
    29     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    30     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    31     return s*t;
    32 }
    33 ll get(int l,int r)
    34 {
    35     return (Hash[r]-(ll)Hash[l-1]*Pow[r-l+1]%MOD+MOD)%MOD;
    36 }
    37 void hashs(char s[])
    38 {
    39     for (int i=0;i<len;i++)
    40       Hash[i]=(ll)(Hash[i-1]*base+s[i])%MOD;
    41 }
    42 int main()
    43 {
    44     mx=0; Pow[0]=1;
    45     while (~scanf("%s",s)){
    46       len=strlen(s); tot=0;
    47       if (len>mx){
    48         for (int i=mx+1;i<=len;i++)
    49           Pow[i]=(ll)Pow[i-1]*base%MOD;
    50           mx=len;
    51       }
    52       hashs(s);    
    53       for (int i=0;i<len;i++)
    54         if (get(0,i)==get(len-i-1,len-1)) ans[++tot]=i+1;
    55       for (int i=1;i<=tot;i++)
    56         out(ans[i]);
    57       writeln;
    58     }
    59     return 0;
    60 }
    View Code

     #10037 「一本通 2.1 练习 3」Friends

    枚举添加字符用hash判一下前后两段是否相同。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll  long long
     9 #define out(a) printf("%d ",a)
    10 #define writeln printf("
    ")
    11 const int N=2e6+50;
    12 const int MOD=1e9+7;
    13 const int base=233;
    14 using namespace std;
    15 char s[N];
    16 int n,len,id;
    17 int num,ans,cnt=0;
    18 bool f,flag;
    19 ll Hash[N],Pow[N];
    20 int read()
    21 {
    22     int s=0,t=1; char c;
    23     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    24     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    25     return s*t;
    26 }
    27 ll readl()
    28 {
    29     ll s=0,t=1; char c;
    30     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    31     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    32     return s*t;
    33 }
    34 ll get(int l,int r)
    35 {
    36     if (l<=r) return (Hash[r]-(ll)Hash[l-1]*Pow[r-l+1]%MOD+MOD)%MOD;
    37     else return 0;
    38 }
    39 ll find(int x)
    40 {
    41     ll y1=0,y2=0;
    42     if (x<=(n>>1)) y1=(get(0,x-1)*Pow[(n>>1)-x]%MOD+get(x+1,n>>1))%MOD,y2=get((n>>1)+1,n-1);
    43     else y1=get(0,(n>>1)-1),y2=(get((n>>1),x-1)*Pow[n-x-1]%MOD+get(x+1,n-1))%MOD;
    44     //out(y1); out(y2); writeln;
    45     if (y1==y2) return y1;
    46     else return 0;
    47 }
    48 int main()
    49 {
    50     n=read();
    51     if (!(n&1)) {
    52       puts("NOT POSSIBLE");
    53       return 0;
    54     }
    55     else {
    56       scanf("%s",s);
    57       len=strlen(s); f=flag=false;
    58       Pow[0]=1;
    59       for (int i=1;i<=len;i++)
    60         Pow[i]=Pow[i-1]*base%MOD;
    61       for (int i=0;i<len;i++)
    62         Hash[i]=(Hash[i-1]*base+s[i])%MOD;
    63       for (int i=0;i<len;i++){
    64         num=find(i);
    65         if (num) {
    66             //out(233); writeln;
    67           if (!f) ans=num,id=i;
    68           else if (ans!=num) {
    69               flag=true; break;
    70           }
    71           f=true;
    72         }
    73       }
    74       if (f) {
    75         if (flag) puts("NOT UNIQUE");
    76         else {
    77           for (int i=0;i<len;i++){
    78             if (i!=id) putchar(s[i]),cnt++;
    79             if (cnt>=(n>>1)) break;
    80           }
    81         }
    82       }
    83       else puts("NOT POSSIBLE");
    84     }
    85       return 0;
    86 }
    87           
    88         
    View Code

    #10038 「一本通 2.1 练习 4」A Horrible Poem

    10035那题的升级版,n≤5e5,而且是询问区间的答案.

     BZOJ 2795: [Poi2012]A Horrible Poem

    #10039 「一本通 2.1 练习 5」Beads

    正反求一波hash值枚举长度然后把hash值扔到map里算一下就好了,loj上wa+mle水了七十多分,洛谷水了tle90分,后来改了个双hash还是wa,找个时间来调吧,flag++。。。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d ",a)
    10 #define writeln printf("
    ")
    11 const int N=2e5+50;
    12 const int MOD=1e9+7;
    13 const int mod=1e9+9;
    14 const int base=2333;
    15 using namespace std;
    16 int n;
    17 int a[N],b[N];
    18 int num,num1,num2,num3,num4,l,ans,tot;
    19 ll Hash1[N],Hash2[N],Hashs1[N],Hashs2[N],Pow[N],Pows[N];
    20 map<int,int>cnt;
    21 map<int,int>cnt2;
    22 int read()
    23 {
    24     int s=0,t=1; char c;
    25     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    26     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    27     return s*t;
    28 }
    29 ll readl()
    30 {
    31     ll s=0,t=1; char c;
    32     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    33     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    34     return s*t;
    35 }
    36 ll get(int l,int r,int x)
    37 {
    38     if (x==1) return (Hash1[r]-(ll)Hash1[l-1]*Pow[r-l+1]%MOD+MOD)%MOD;
    39     return (Hash2[l]-(ll)Hash2[r+1]*Pow[r-l+1]%MOD+MOD)%MOD;
    40 }
    41 ll get2(int l,int r,int x)
    42 {
    43     if (x==1) return (Hashs1[r]-(ll)Hashs1[l-1]*Pows[r-l+1]%mod+mod)%mod;
    44     return (Hashs2[l]-(ll)Hashs2[r+1]*Pows[r-l+1]%mod+mod)%mod;
    45 }
    46 void hash1()
    47 {
    48     for (int i=1;i<=n;i++){
    49       Hash1[i]=(Hash1[i-1]*base+a[i])%MOD;
    50       Hashs1[i]=(Hashs1[i-1]*base+a[i])%mod;
    51     }
    52 }
    53 void hash2()
    54 {
    55     for (int i=n;i;i--){
    56       Hash2[i]=(Hash2[i+1]*base+a[i])%MOD;
    57       Hashs2[i]=(Hashs2[i-1]*base+a[i])%mod;
    58     }
    59 }
    60 int main()
    61 {
    62 //    freopen("beads.in","r",stdin);
    63 //    freopen("beads.out","w",stdout);
    64     n=read(); ans=-23333333;
    65     for (int i=1;i<=n;i++)
    66       a[i]=read();
    67     hash1(); hash2(); Pow[0]=1;
    68     for (int i=1;i<=n;i++){
    69       Pow[i]=Pow[i-1]*base%MOD;
    70       Pows[i]=Pows[i-1]*base%mod;
    71     }
    72     for (int i=1;i<=n;i++){
    73       num=0;
    74       if (n/i<ans) break;
    75       for (int j=1;j<=n;j+=i){
    76           if (j+(i-1)>n) break;
    77         num1=get(j,j+(i-1),1); num2=get(j,j+(i-1),2);
    78         num3=get(j,j+(i-1),1); num4=get(j,j+(i-1),2);
    79         if ((!cnt[num1]&&!cnt[num2])||(!cnt2[num3]&&!cnt2[num4])) 
    80           num++,cnt[num1]++,cnt[num2]++,cnt2[num3]++,cnt2[num4]++;
    81       }
    82      // if (i==199) out(num);
    83       if (num==ans) b[++tot]=i;
    84       else if (num>ans) {
    85         ans=num;
    86         tot=0; 
    87         b[++tot]=i; 
    88       } 
    89     }
    90     out(ans); out(tot); writeln;
    91     for (int i=1;i<=tot;i++)
    92       out(b[i]);
    93 }
    View Code

     #10040. 「一本通 2.1 练习 6」Antisymmetry

    BZOJ 2084: [Poi2010]Antisymmetry

    第 2 章 KMP 算法

    #10043 「一本通 2.2 例 1」剪花布条

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=5e5+50;
    12 using namespace std;
    13 int len1,len2;
    14 int nxt[N];
    15 char c,s1[N],s2[N];
    16 int read()
    17 {
    18      int s=0,t=1; char c;
    19      while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    20      while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    21      return s*t;
    22 }
    23 ll readl()
    24 {
    25      ll s=0,t=1; char c;
    26      while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    27      while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    28      return s*t;
    29 }
    30 void pre()
    31 {
    32     nxt[1]=0;
    33     int j=0;
    34     for (int i=1;i<len2;i++){
    35       while (j&&s2[j+1]!=s2[i+1]) j=nxt[j];
    36       if (s2[j+1]==s2[i+1]) j++;
    37       nxt[i+1]=j;
    38     }
    39 }
    40 int kmp()
    41 {
    42     int j=0,ans=0;
    43     for (int i=0;i<len1;i++){
    44       while (j&&s2[j+1]!=s1[i+1]) j=nxt[j];
    45       if (s2[j+1]==s1[i+1]) j++;
    46       if (j==len2) ans++,j=0;
    47     }
    48     return ans;
    49 }
    50 int main()
    51 {
    52     while (~scanf("%s",s1+1)){
    53       if (s1[1]=='#'&&strlen(s1+1)==1) break;
    54       c=getchar(); scanf("%s",s2+1);
    55       len1=strlen(s1+1); len2=strlen(s2+1);
    56       //cout<<len1<<endl;
    57       pre();
    58       out(kmp()); writeln;
    59     }
    60     return 0;
    61 }
    62       
    View Code

    #10035. 「一本通 2.1 练习 1」Power Strings

    不重叠的话就每次从模式串第一位开始找就可以保证。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int len;
    15 int nxt[N];
    16 char s[N];
    17 int read()
    18 {
    19     int s=0,t=1; char c;
    20     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    21     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    22     return s*t;
    23 }
    24 ll readl()
    25 {
    26     ll s=0,t=1; char c;
    27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    29     return s*t;
    30 }
    31 void pre()
    32 {
    33     nxt[1]=0;
    34     int j=0;
    35     for (int i=1;i<len;i++){
    36         while (j&&s[j+1]!=s[i+1]) j=nxt[j];
    37         if (s[i+1]==s[j+1]) j++;
    38         nxt[i+1]=j;
    39     }
    40 }
    41 int main()
    42 {
    43     while (~scanf("%s",s+1)){
    44       if (s[1]=='.') break;
    45       len=strlen(s+1);
    46       pre();
    47       if (len%(len-nxt[len])==0) out(len/(len-nxt[len]));
    48       else out(1);
    49       writeln;
    50     }
    51     return 0;
    52 }
    View Code

    #10045. 「一本通 2.2 练习 1」Radio Transmission

    BZOJ 1355: [Baltic2009]Radio Transmission

    #10049. 「一本通 2.3 例 1」Phone List

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int T,n;
    15 int tot;
    16 int trie[N][10];
    17 char s[N];
    18 bool flag,f2,f[N];
    19 int read()
    20 {
    21     int s=0,t=1; char c;
    22     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    23     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    24     return s*t;
    25 }
    26 ll readl()
    27 {
    28     ll s=0,t=1; char c;
    29     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    30     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    31     return s*t;
    32 }
    33 bool insert(char *s)
    34 {
    35     int u=1; int len=strlen(s);
    36     bool flag=false;
    37     for (int i=0;i<len;i++){
    38       int c=s[i]-'0';
    39       if (!trie[u][c]) trie[u][c]=++tot;
    40       else if (i==len-1) flag=true;
    41       u=trie[u][c];
    42       if (f[u]) flag=true;
    43     }
    44     f[u]=true;
    45     return flag;
    46 }
    47 int main()
    48 {
    49             
    50 //freopen("beads.in","r",stdin);
    51 //    freopen("beads.out","w",stdout);
    52     T=read();
    53     while (T--){
    54       n=read(); tot=1;
    55       memset(trie,0,sizeof(trie));
    56       memset(f,false,sizeof(f)); f2=false;
    57       for (int i=1;i<=n;i++){
    58           scanf("%s",s); 
    59           if (insert(s)) 
    60          f2=true; 
    61       }
    62       if (!f2) puts("YES");
    63       else puts("NO");
    64     }
    65     return 0;
    66 }
    View Code

    #10050. 「一本通 2.3 例 2」The XOR Largest Pair

    01trie经典题

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%lld",a)
    10 #define writeln printf("
    ")
    11 const int N=1e5+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int n;
    15 int tot;
    16 ll ans,x;
    17 int trie[N*32][2];
    18 int read()
    19 {
    20     int s=0,t=1; char c;
    21     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    22     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    23     return s*t;
    24 }
    25 ll readl()
    26 {
    27     ll s=0,t=1; char c;
    28     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    29     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    30     return s*t;
    31 }
    32 void insert(ll x)
    33 {
    34     int u=1;
    35     for (int i=31;i>=0;i--){
    36       int c=((1<<i)&x)>0;
    37       if (!trie[u][c]) trie[u][c]=++tot;
    38       u=trie[u][c];
    39     }
    40 }
    41 ll find(ll x)
    42 {
    43     int u=1; ll res=0;
    44     for (int i=31;i>=0;i--){
    45       int c=((1<<i)&x)>0;
    46       if (trie[u][1-c]) {
    47           u=trie[u][1-c];  res+=(1<<i);
    48         continue;
    49       }
    50       u=trie[u][c];
    51     }
    52     return res;
    53 }
    54 int main()
    55 {
    56     n=read(); tot=1;
    57     ans=-23333333;
    58     for (int i=1;i<=n;i++){
    59       x=readl(); insert(x); 
    60       if (ans<find(x)) ans=find(x);
    61     }
    62     out(ans);
    63     return 0;
    64 }
    65           
    View Code

    #10051. 「一本通 2.3 例 3」Nikitosh 和异或

    BZOJ 4260: Codechef REBXOR(01trie+思维)

    #10052. 「一本通 2.3 练习 1」Immediate Decodability

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define writeln printf("
    ")
    11 const int N=1e6+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int cnt=0,tot=1;
    15 char s[N];
    16 bool flag,f[N];
    17 int trie[N][10];
    18 int read()
    19 {
    20     int s=0,t=1; char c;
    21     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    22     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    23     return s*t;
    24 }
    25 ll readl()
    26 {
    27     ll s=0,t=1; char c;
    28     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    29     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    30     return s*t;
    31 }
    32 bool insert(char *s)
    33 {
    34     int u=1; int len=strlen(s);
    35     bool ff=false;
    36     for (int i=0;i<len;i++){
    37       int c=s[i]-'0';
    38       if (!trie[u][c]) trie[u][c]=++tot;
    39       else if (i==len-1) ff=true;
    40       u=trie[u][c];
    41       if (f[u]) ff=true;
    42     }
    43     f[u]=true;
    44     return ff;
    45 }
    46 int main()
    47 {
    48     flag=false;
    49     while (~scanf("%s",s)){
    50       if (s[0]=='9'&&strlen(s)==1) {
    51           if (flag) printf("%s %d %s
    ","Set",++cnt,"is not immediately decodable");
    52           else printf("%s %d %s
    ","Set",++cnt,"is immediately decodable");
    53         memset(f,false,sizeof(f));
    54         memset(trie,0,sizeof(trie)); flag=false; tot=1;
    55       }
    56       else if (insert(s)) flag=true;
    57     }
    58     return 0;
    59 }
    60             
    View Code

    #10056. 「一本通 2.3 练习 5」The XOR-longest Path

     BZOJ 1954: Pku3764 The xor-longest Path(01trie)

    第三部分 图论

    第 1 章 最小生成树

    #10066 「一本通 3.1 练习 1」新的开始

    建多一个点0表示发电站,然后其他点往他连边,跑一遍kruskal就没了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define ln printf("
    ")
    11 const int N=1e5+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int n;
    15 int v,p,tot=0;
    16 int pre[N];
    17 int ans=0;
    18 struct node
    19 {
    20     int x,y,cost;
    21 }edge[N];
    22 int read()
    23 {
    24     int s=0,t=1; char c;
    25     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    26     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    27     return s*t;
    28 }
    29 ll readl()
    30 {
    31     ll s=0,t=1; char c;
    32     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    33     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    34     return s*t;
    35 }
    36 void add(int x,int y,int z)
    37 {
    38     edge[++tot].x=x;
    39     edge[tot].y=y;
    40     edge[tot].cost=z;
    41 }
    42 int find(int x)
    43 {
    44     if (pre[x]==x) return x;
    45     else return pre[x]=find(pre[x]);
    46 }
    47 void Kruskal()
    48 {
    49     int x,y;
    50     for (int i=1;i<=tot;i++){
    51           x=find(edge[i].x); y=find(edge[i].y);
    52         if (x!=y){
    53           pre[x]=y;
    54           ans+=edge[i].cost; 
    55         }
    56     }
    57 }
    58 bool cmp(node a,node b)
    59 {
    60     return a.cost<b.cost;
    61 }
    62 int main()
    63 {
    64     n=read();
    65     for (int i=1;i<=n;i++)
    66       v=read(),add(0,i,v),add(i,0,v),pre[i]=i;
    67     for (int i=1;i<=n;i++)
    68       for (int j=1;j<=n;j++)
    69         p=read(),add(i,j,p);
    70     sort(edge+1,edge+tot+1,cmp);
    71     Kruskal();
    72     out(ans);
    73     return 0;
    74 }
    View Code

     第 2 章 最短路

    #10074 「一本通 3.2 例 3」架设电话线

     在加权无向图上求出一条从 1号结点到 N号结点的路径,使路径上第 K+1大的边权尽量小。

    看了题解。。。

    二分答案,把权值大于mid的边权设为1,否则设为0,跑1到n的最短路.

    如果dis[n]>k,那么mid太小,向上缩小区间,否则反之.

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define ln printf("
    ")
    11 const int N=1e5+50;
    12 const int MOD=1e9+7;
    13 using namespace std;
    14 int n,m,k;
    15 int x,y,z;
    16 int l,r,mid;
    17 int head[N],dis[N];
    18 int tot=0;
    19 bool vis[N],flag;
    20 struct node
    21 {
    22     int to,cost,nxt;
    23 }edge[N];
    24 int read()
    25 {
    26     int s=0,t=1; char c;
    27     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    28     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    29     return s*t;
    30 }
    31 ll readl()
    32 {
    33     ll s=0,t=1; char c;
    34     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    35     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    36     return s*t;
    37 }
    38 void add(int x,int y,int z)
    39 {
    40     edge[++tot].to=y;
    41     edge[tot].cost=z;
    42     edge[tot].nxt=head[x];
    43     head[x]=tot;
    44 }
    45 struct dist
    46 {
    47     int id,h;
    48     bool operator<(const dist&a)const{
    49         return a.h<h;
    50     }
    51 };
    52 priority_queue<dist>q;
    53 void Dijkstra(int v)
    54 {
    55     int x,y,z;
    56     memset(dis,127,sizeof(dis));
    57     memset(vis,false,sizeof(vis)); 
    58     dist p; dis[1]=0;
    59     p.id=1; p.h=0;
    60     q.push(p);
    61     while (!q.empty()){
    62       p=q.top(); q.pop();
    63       x=p.id;
    64       if (!vis[x]){
    65         vis[x]=true;
    66         for (int i=head[x];i;i=edge[i].nxt){
    67           y=edge[i].to; z=edge[i].cost;
    68           if (dis[y]>dis[x]+(z<=v?0:1)){
    69               dis[y]=dis[x]+(z<=v?0:1);
    70               p.id=y; p.h=dis[y];
    71               q.push(p);
    72           }
    73         }
    74       }
    75     }
    76 }
    77 bool check()
    78 {
    79     return dis[n]>k?false:true;
    80 }
    81 int main()
    82 {
    83     n=read(),m=read(),k=read(); l=0; flag=false;
    84     for (int i=1;i<=m;i++)
    85       x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z),r+=z;
    86     while (l<=r){
    87       mid=(l+r)>>1;
    88       Dijkstra(mid);
    89       if (dis[n]<=1000) flag=true;
    90       if (!check()) l=mid+1;
    91       else r=mid-1;
    92     }
    93     if (flag) out(l);
    94     else puts("-1");
    95     return 0;
    96 }
    View Code

    #10075 「一本通 3.2 练习 1」农场派对

    从x和其他各点为起点跑最短路,加起来找个最大就行了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <queue>
     7 #include <map>
     8 #define ll long long
     9 #define out(a) printf("%d",a)
    10 #define ln printf("
    ")
    11 #define clear(a,b) memset(a,b,sizeof(a))
    12 const int N=1e5+50;
    13 const int MOD=1e9+7;
    14 using namespace std;
    15 int n,m,s;
    16 int x,y,z,tot=0;
    17 int dis[N],a[N];
    18 int head[N];
    19 bool vis[N];
    20 int ans=-23333333;
    21 struct node
    22 {
    23     int to,nxt,cost;
    24 }edge[N];
    25 struct dist
    26 {
    27     int h,id;
    28     bool operator<(const dist&a)const{
    29       return a.h<h;
    30     }
    31 };
    32 int read()
    33 {
    34     int s=0,t=1; char c;
    35     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    36     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    37     return s*t;
    38 }
    39 ll readl()
    40 {
    41     ll s=0,t=1; char c;
    42     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
    43     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
    44     return s*t;
    45 }
    46 void add(int x,int y,int z)
    47 {
    48     edge[++tot].to=y;
    49     edge[tot].cost=z;
    50     edge[tot].nxt=head[x];
    51     head[x]=tot;
    52 }
    53 priority_queue<dist>q;
    54 void Dijkstra(int s)
    55 {
    56     clear(dis,127); clear(vis,false);
    57     dis[s]=0;
    58     dist p;
    59     p.h=0; p.id=s;
    60     q.push(p);
    61     while (!q.empty()){
    62       p=q.top(); q.pop();
    63       x=p.id;
    64       if (!vis[x]){
    65           vis[x]=true;
    66           for (int i=head[x];i;i=edge[i].nxt){
    67             y=edge[i].to; z=edge[i].cost;
    68             if (dis[y]>dis[x]+z){
    69                 dis[y]=dis[x]+z;
    70                 p.h=dis[y]; p.id=y;
    71                 q.push(p);
    72             }
    73         }
    74       }
    75     }
    76 }
    77 int main()
    78 {
    79     n=read(),m=read(),s=read();
    80     for (int i=1;i<=m;i++){
    81       x=read(),y=read(),z=read();
    82       add(x,y,z);
    83     }
    84     Dijkstra(s); 
    85     for (int i=1;i<=n;i++)
    86       a[i]=dis[i];
    87     for (int i=1;i<=n;i++)
    88       if  (i!=s){
    89         Dijkstra(i);
    90         ans=max(ans,a[i]+dis[s]);
    91       }
    92     out(ans);
    93     return 0;
    94 }
    View Code

     

  • 相关阅读:
    如何使用类
    面向过程编程与面向对象优缺点
    生成器和迭代器的藕断丝连
    三元运算
    python 和pycharm 安装
    命令提示符玩法
    模块
    包(package)
    logging模块
    1964、1969和1972---------为什么中国互联网大佬出生在这3个年份
  • 原文地址:https://www.cnblogs.com/Kaleidoscope233/p/9477890.html
Copyright © 2020-2023  润新知