12.23 [diary] / [explanations] CF Edu78

12.23 Diary

DP

  1. Luo Gu P1280: N minute weekday, there are K tasks, each task from the \ (p_i \) minutes, lasted \ (t_i \) minutes each time If there are multiple tasks to complete, you can optionally one, but you can only do a job, ask how to select the task, making the most spare time. Data 1e4.

Thinking: DP [I] represents iN minutes, the maximum idle time. Then traverse forward from the back of each task, this is no after-effect of the previous task how the election is irrelevant. So first descending order of task start time, and then turn from time n-1 dp can begin.

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+20;
struct T{
    int st,dur;
    bool operator<(const T &x)const{
        return st>x.st;
    }
};
struct Task{
    int n,k,dp[M];
    T a[M];
    void init(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=k;++i)
            scanf("%d%d",&a[i].st,&a[i].dur);
    }
    void run(){
        sort(a+1,a+k+1);
        int p=1;
        for(int i=n;i>=1;--i)
            if (a[p].st!=i)
                dp[i]=dp[i+1]+1;
            else
                while(a[p].st==i)
                    dp[i]=max(dp[i],dp[i+a[p].dur]),++p;
        printf("%d\n",dp[1]);
    }
}task;
int main(){
    task.init(),task.run();
    return 0;
}

CF Edu78

A. Shuffle Hashing

Question is intended: to define the hash string s and h, s of the s random disrupted, after adding an arbitrary prefix and a suffix any, of the resulting string is the hash s, now may be asked whether s h the hash.

Idea: to traverse the length of the interval all h len (s), and count the number of each character, and if the number s of each character as it is possible. Time complexity \ (O (^ n-2) \) .

#include<bits/stdc++.h>
using namespace std;
const int M=1e2+50;
struct T{
    int ans[28],now[28],len1,len2;
    char s1[M],s2[M];
    void init(){
        for(int i=0;i<26;++i)
            ans[i]=now[i]=0;
        scanf("%s%s",s1,s2);
        len1=strlen(s1),len2=strlen(s2);
    }
    inline bool check(){
        for(int i=0;i<26;++i)
            if (ans[i]!=now[i])
                return false;
        return true;
    }
    void run(){
        init();
        if(len2<len1){
            printf("NO\n");
            return;
        }
        for(int i=0;i<len1;++i)
            ++ans[s1[i]-'a'],++now[s2[i]-'a'];
        int p=len1;
        while(p<len2&&!check())
            --now[s2[p-len1]-'a'],++now[s2[p]-'a'],++p;
        if (check())
            printf("YES\n");
        else
            printf("NO\n");
    }
}t;
int main(){
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;++i)
        t.run();
    return 0;
}

B. A and B

Question is intended: to two numbers a and B, the k is a number selected operations, to add k. Output such that the minimum number of steps a and b are equal.

Ideas: ! A and b calculated difference d, then find the first x, such that x (x + 1) / 2 > = d ( i.e. Crazy added to the small numbers), if d = 0, then this when a and b is not the same. The question then converted to the x (x + 1) / 2 is divided into two numbers, so that the phase difference d. That depends on x (x + 1) / 2 + d is an even number, if it is odd, the need to continue to increase until up to an even number, so as to be divided into an integer. It is easy to understand some added no more than 2 times.

Time complexity \ (O (\ log n-) \) .

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define mid ((l+r)>>1)
struct T{
    int a,b,d;
    void init(){
        scanf("%d%d",&a,&b);
        d=abs(a-b);
    }
    bool check(int x){
        if (1LL*x*(x+1)/2>=d)
            return true;
        return false;
    }
    void run(){
        init();
        int l=0,r=1e5+20;
        while(l!=r){
            if (check(mid))
                r=mid;
            else
                l=mid+1;
        }
        while((1LL*l*(l+1)/2+d)%2==1)
            ++l;
        printf("%d\n",l);
    }
}t;
int main(){
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;++i)
        t.run();
    return 0;
}

C.Berry hour

Question is intended: to 2n cans, a standing start between the n and n + 1, each can is 1 or 2, and may be selected in eaten all n + 1-j canned in two sections. Q. How many cans least need to eat in order to make the remaining number 1 and 2 are equal.

Solution: Suppose a number> 2 number, the first number is calculated to be eaten by an additional 1, denoted by x. After calculating the time to hit 1 + 1, 2 touch to -1. First calculate n go to the left, on each through a + 1 / -1. It is contemplated that if i was at the sum, j is also at the sum, and i <j, then i certainly useless. So for each sum, only you need to record the first j can arise. Then the position can occur into an array or queue. The same treatment to the right. After the enumeration left x 0 Right, left and right x-1 x 1 ...... left and right 0, calculate the number of cans in each case according to eat recorded position, to a minimum value, may not pay attention to handling the left x Case.

Time complexity \ (O (n-) \) .

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+20;
#define tr(x) (x==pd?1:-1)
struct pl{
    int val,num;
    pl(int a=0,int b=0):val(a),num(b){};
};
struct T{
    int n,a[M*2],num[3],pd,dt,sum,ans;
    void init(){
        scanf("%d",&n);
        num[1]=num[2]=0;
        for(int i=1;i<=2*n;++i)
            scanf("%d",&a[i]),++num[a[i]];
        dt=abs(num[1]-num[2]),ans=1e9+7;
    }
    int run(){
        init();
        if (num[1]==num[2])
            return 0;
        if (num[1]>num[2])
            pd=1;
        else
            pd=2;
        deque<pl> l,r;
        sum=0;
        l.push_back(pl(0,0));
        for(int i=n;i>=1;--i){
            sum+=tr(a[i]);
            if (sum>l.back().val)
                l.push_back(pl(sum,n-i+1));
        }
        sum=0;
        r.push_back(pl(0,0));
        for(int i=n+1;i<=2*n;++i){
            sum+=tr(a[i]);
            if (sum>r.back().val)
                r.push_back(pl(sum,i-n));
        }
        while(!l.empty()){
            if (l.front().val>dt)
                break;
            while(r.back().val>dt-l.front().val)
                r.pop_back();
            if (r.back().val+l.front().val==dt)
                ans=min(ans,l.front().num+r.back().num);
            l.pop_front();
        }
        return ans;
    }
}t;
int main(){
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;++i)
        printf("%d\n",t.run());
    return 0;
}

D. Segment Tree

The meaning of problems: for n points, each point represents an interval \ ([L_i, r_i] \) , to ensure that all of l, r not repeated. If both intervals overlap, but does not include, between two edge points there. I asked whether this figure is a tree.

Thinking: This could be considered a data structure that the result will not do ..................

According to the interval l small to large order, read each section will be placed in the right spot and number set, then put in before, set in the remaining element is the element with whom edge. If the set point is too small right there on the edge deleted. Obviously, if found more than n-1 edges, then directly NO. If exactly n-1 edges, can then determine connectivity. It can be disjoint-set.

Time complexity \ (O (n-\ log n-) \) .

Tomorrow to fix it.

Guess you like

Origin www.cnblogs.com/diorvh/p/12089254.html