$2019 $Summer Rewrite Record $2 (Basic Algorithms Project)

Posted by zulfer on Fri, 26 Jul 2019 05:41:31 +0200

\ (2019) Summer Scrubbing Records (2\\\\) Basic Algorithms

\(by~~wch\)

\(BZOJ~1958~Strange~Towers~of~Hanoi\) (Dynamic programming, recursion)

Main idea of the title:

The problem of Hanoi Tower with (n) plates and (4) towers is solved.

\(solotion:\)

  1. First of all, we need to refer to the Hanoi Tower of the three towers: (g[i]=2*g[i-1]+1)
  2. Then we will convert the four towers into three towers: the former \\\\\\\\\\\\\\\
  3. \(f[n]=min_{1\leq i < n}{2*f[i]+g[n-i]}\)

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

int n=12;
int g[13],f[13];

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    for(rg i=1;i<=n;++i) g[i]=2*g[i-1]+1;
    for(rg i=1;i<=n;++i){
        f[i]=1<<30;
        for(rg j=0;j<i;++j)
            f[i]=min(f[i],f[j]*2+g[i-j]);
    }
    for(rg i=1;i<=n;++i)
        printf("%d\n",f[i]);
    return 0;
}

BZOJ ~1218 ~$Laser Bomb (2-D prefix sum)

\(solotion:\)

  1. Two-Dimensional Prefixes and Problems
  2. It's just that this problem is a bit stubborn. If violence turns to one-dimensional prefix, it will run out of time.
  3. We need to find the relationship between each dot prefix and sum by ourselves:
  4. \(s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]\)

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

int n,m,ans,a,b,c;
int f[5003][5003];

inline int qr(){
    char ch; //int sign=1;
    while((ch=getchar())<'0'||ch>'9');
    //    if(ch=='-')sign=-1;
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr(),m=qr();
    for(rg i=1;i<=n;++i){
        a=qr()+1,b=qr()+1,c=qr();
        f[a][b]=c;
    }
    for(rg i=1;i<=5001;++i)
        for(rg j=1;j<=5001;++j)
            f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
    for(rg i=m;i<=5001;++i){
        for(rg j=m;j<=5001;++j){
            ans=max(ans,f[i][j]-f[i-m][j]-f[i][j-m]+f[i-m][j-m]);
        }
    }printf("%d\n",ans);
    return 0;
}

\(POJ~3263~Tallest~Cow\) (prefix and greed)

\(solotion:\)

  1. A long time ago, a more interesting prefix and Practice
  2. First of all, we can greedily think that the cow's height is reduced by only 1 at a time, and then we can find the least reduction times.
  3. The number of height reductions per cow is certain. For each pair of cattle that can see each other, the height of the cattle among them should be reduced once.
  4. So we add one at (A_i), subtract one at (B_i+1) and find the prefix sum to know the reduction times of each cow.
  5. Next, there is no need to worry that each cow is shorter than the two ends of the cow. All intervals must be inclusive, not intersecting.

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

int n,m,h,q,a,b;
int s[10001];
bool use[10001][10001];

inline int qr(){
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    int res=ch^48;
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+(ch^48);
    return res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr(),m=qr(),h=qr(),q=qr();
    while(q--){
        a=qr(),b=qr();
        if(a>b)swap(a,b);
        if(use[a][b])
            continue;
        use[a][b]=1;
        --s[a+1];
        ++s[b];
    }
    for(rg i=1;i<=n;++i){
        s[i]=s[i]+s[i-1];
        printf("%d\n",h+s[i]);
    }
    return 0;
}

\(POJ~1845~Sumdiv\) (approximation and theorem) (divide and conquer)

Main idea of the title:

Find the sum of all approximations of (A^B)

\(solotion:\)

  1. First, we need to know the approximation and theorem: ((1+p_1+p_1^2+...+p_1^{c_1})* (1+p_2+p_2^2+...+p_2^{c_2})* ((1+p_k+p_k^2++p_k^{c_k})\)
  2. Then the problem is better done. The sum of all the approximate numbers of (A^B) is to multiply (c_i) by (B\)
  3. Then the things in parentheses can be solved directly by dividing and conquering.

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

const int mod=9901;

int n,m,ans;

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

inline int ksm(ll x,int y){
    ll res=1;
    while(y){
        if(y&1)res=res*x%mod;
        x=x*x%mod; y>>=1;
    }return res;
}

inline int ask(int x,int y){
    if(y==1)return x;
    if(y&1) return ((ll)ask(x,y>>1)*(ksm(x,y>>1)+1)%mod+ksm(x,y)%mod)%mod;
    else return (ll)ask(x,y>>1)*(ksm(x,y>>1)+1)%mod;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    while(~scanf("%d%d",&n,&m)){
        if(m==0){puts("1");continue;}
        ans=1;
        for(rg i=2;i*i<=n;++i){
            if(n%i)continue;
            rg x=0; while(!(n%i))++x,n/=i;
            ans=(ll)ans*(ask(i%mod,x*m)+1)%mod;
        }if(n!=1)ans=(ll)ans*(ask(n%mod,m)+1)%mod;
        printf("%d\n",ans);
    }
    return 0;
}

\(POJ~2018~Best~Cow~Fences\) (Binary Answers Construct New Weights)

A Solitary Problem

\(POJ~3889~Fractal~Streets\) (simulation)

A Solitary Problem

\(Codeforces~670C~Cinema\) (discretization)

\(solotion:\)

  1. It's a silly question to find the corresponding person in each language directly by discretization.
  2. Then enumerate the movies and get their weights. The biggest one is the answer.

\(code:\)

#include<stdio.h>
#include<map>
using namespace std;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int m,ple=0,sat=0,fi=1,sci[200005],bn[200005],cn;
        map<int,int> mp;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&sci[i]);
            mp[sci[i]]++;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&bn[i]);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&cn);
            if(mp[bn[i]]>ple)
            {
                ple=mp[bn[i]];
                sat=mp[cn];
                fi=i;
            }
            else if(mp[bn[i]]==ple&&mp[cn]>sat)
            {
                sat=mp[cn];
                fi=i;
            }
        }  
        printf("%d\n",fi);
    }
    return 0;
}

\(POJ~3784~Running~Media\) (Dynamic median)

Main idea of the title:

Read in sequence to find the median of each number when it is added.

\(solotion:\)

  1. Just use the small root pile to enlarge the root pile and maintain it.
  2. Record the total number on both sides and decide which side to add.

\(code:\)

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;

int n,t,x,a,b,cnt;

inline void read(int &x){
    char ch=getchar();
    char c=ch;
    x=0;
    while(ch<'0' || ch>'9') {
        c=ch;
        ch=getchar();
    }
    while(ch>='0' && ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    if(c== '-') x=-x;
}

std::priority_queue <int> lq,sq;


int main(){
    read(t);
    while(t--){
        read(cnt);
        read(n);
        while(!lq.empty())  lq.pop();
        while(!sq.empty())  sq.pop();
        cout<<cnt<<' '<<((n+1)/2)<<endl;
        for(int i = 1;i <= n;++ i){
            read(x);
            lq.push(x);
            sq.push(-x);
            if(i%2==0) continue;
            while(lq.top()!=-sq.top()){
                a=lq.top();
                lq.pop();
                b=-sq.top();
                sq.pop();
                sq.push(-a);
                lq.push(b);
            }
            cout<<lq.top()<<' ';
            if(((i+1)/2)%10==0) puts("");
                else if((n%2==1 && i==n) || (n%2==0 && i==n-1)) puts("");
        }    
    }
    return 0;
}

\(POJ~2299~Ultra-QuickSort\) (Reverse order pair)

Main idea of the title:

Find an inverse pair in a sequence.

\(solotion:\)

  1. I didn't expect to encounter this in the basic algorithm. I miss it very much.
  2. Let's maintain it with a tree array (which needs to be discretized), and Longest ascending subsequence Inside a board

\(POJ~3614~Sunscreen\) (Greed, priority queue)

\(solotion:\)

  1. It's easy to think of greed on this topic.
  2. We separate dairy cows from sunscreen in order of minimum sunshine intensity.
  3. Then we can think of enumerating sunscreen.
  4. Use a priority queue to conserve cattle currently protected by sunscreen
  5. Then we used the priority queue to find the right-end (maximum sunshine intensity) minimum cow to use this sunscreen.
  6. This is definitely better than maximum sunshine intensity, because we leave the maximum sunshine intensity behind the sunscreen.
  7. The minimum sunshine intensity is guaranteed when enumerating (we add sunscreen in turn to protect cattle).

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

int n,m,ans;

struct su{
    int x,y;
    inline bool operator <(const su &z)const{
        return x<z.x;
    } 
}a[2505],b[2505];

struct pi{
    int x,y;
    inline bool operator <(const pi &z)const{
        return y>z.y;
    }
};

priority_queue<pi> q;

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr(); m=qr();
    for(rg i=1;i<=n;++i)
        a[i].x=qr(),a[i].y=qr();
    sort(a+1,a+n+1);
    for(rg i=1;i<=m;++i)
        b[i].x=qr(),b[i].y=qr();
    sort(b+1,b+m+1);
    for(rg i=1,l=1;i<=m;++i){
        while(l<=n&&a[l].x<=b[i].x){
            pi x; x.x=l; x.y=a[l].y; q.push(x); ++l;
        }
        while(!q.empty()&&q.top().y<b[i].x)q.pop();
        while(!q.empty()&&b[i].y){
            ++ans; --b[i].y; q.pop();
        }
    }printf("%d\n",ans);
    return 0;
}

\(POJ~3190~Stall~Reservation\) (prefix and, priority queue)

\(solotion:\)

  1. The minimum number of hurdles in this question is determined.
  2. We can get the answer directly by using difference constrained prefix sum method.
  3. But this also requires us to export the serial number of the livestock railings, which requires us to dynamically maintain those livestock railings that have not been used.
  4. We use priority queue optimization to enumerate each cow according to the left endpoint, and then record its right endpoint and which fence it uses with priority queue. (The use status of the fence also needs to be maintained with a priority queue (because we want to minimize the number of fences).)
  5. Then in the enumeration process, the priority queue is taken out, the depleted animal pen is recorded, and the ward will be in the priority queue.

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

int n,tt,ans;
int as[50005];

struct su{
    int l,r,id;
    inline bool operator <(const su &x)const{
        return l<x.l;
    }
}a[50005];

struct pi{
    int x,y;
    inline bool operator <(const pi &z)const{
        return x>z.x;
    }
};

priority_queue<pi> q;
priority_queue<int, vector<int>, greater<int> >p;

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr();
    for(rg i=1;i<=n;++i)
        a[i].l=qr(),a[i].r=qr(),a[i].id=i,p.push(i);
    sort(a+1,a+n+1);
    for(rg i=1;i<=n;++i){
        while(!q.empty()&&q.top().x<a[i].l){
            p.push(q.top().y); q.pop();
        }as[a[i].id]=p.top(); p.pop();
        pi x; x.x=a[i].r; x.y=as[a[i].id]; q.push(x);
        ans=max(ans,as[a[i].id]);
    }
    printf("%d\n",ans);
    for(rg i=1;i<=n;++i)
        printf("%d\n",as[i]);
    return 0;
}

Topics: PHP Programming