2018 黑龙江省大学生程序设计竞赛

A Count Task

题面:

Count is one of WNJXYK’s favorite tasks. Recently, he had a very long string and he wondered that how many substrings which contains exactly one kind of lowercase in this long string. But this string is so long that he had kept counting for several days. His friend Kayaking wants to help him, so he turns to you for help.

InputThe input starts with one line contains exactly one positive integer $T$ which is the number of test cases.
Each test case contains one line with a string which you need to do a counting task on.OutputFor each test case, output one line containing “y” where y is the number of target substrings.Sample Input

3
qwertyuiop
qqwweerrttyyuuiioopp
aaaaaaaaaa

Sample Output

10
30
55

Hint

1<=T<=20,1<=len(string)<=10^5,1<=∑len(string)<=10^5
Strings only contain lowercase English letters.

题解:

计算每个单词的对相同的单词段的贡献度,然后累和。

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
ll n,m,t,k,ans,cnt;
int a[mxn] , b[mxn] , c[2*mxn] , d[mxn] , vis[mxn];
void solve() 
{
    string str ;
    for(cin>>t;t;t--){
        cin>>str;
        ans = 0 ;
        for(int i=0;i<str.size();i++){
            k = 1;
            while(str[i]==str[i+1] && i<str.size())
                k++ , i++ ;
            ans+=(1+k)*k/2;
        }
        cout<<ans<<endl;
    }    
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

A Sequence Game

题面:

 

One day, WNJXYK found a very hard problem on an Online Judge. This problem is so hard that he had been thinking about the solutions for a couple of days. And then he had a surprise that he misunderstood that problem and easily figured out a solution using segment tree. Now he still wonders that solution for the misread problem.
There is a sequence with NN positive integers A1A1,A2A2,...,AnAn and MM queries. Each query will give you an interval [L,R] and require an answer with YES/NO indicates that whether the numbers in this interval are continuous in its integer range.
Let us assume that the maximal number in an interval is mxmx and the minimal number is mimi. The numbers in this interval are continuous in its integer range means that each number from mimi to mxmx appears at least once in this interval.

InputThe input starts with one line contains exactly one positive integer TT which is the number of test cases. And then there are T cases follow.
The first line contains two positive integers nn,mm which has been explained above.The second line contains positive integers A1A1,A2A2,...,AnAn.
Then there will be m lines followed. Each line contains to positive numbers LiLi,RiRi indicating that the ith query’s interval is [LiLi,RiRi].
OutputFor each test case, output m line.
Each of following m lines contains a single string “YES”/ “NO” which is the answer you have got.Sample Input

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

Sample Output

YES YES NO NO YES YES

Hint

T=5
1<=n<=100000
1<=Ai<=10^9
1<=m<=100000
The input file is very large, so you are recommend to use scanf() and printf() for IO.

 题解:

莫队的学习

#include <bits/stdc++.h>
const int mxn = 1e5+7 ;
using namespace std;
typedef long long ll;
 
int t,n,m,block,lg[mxn],a[mxn],b[mxn],mx[mxn][35],mn[mxn][35],cur=0,cnt[mxn];
bool ans[mxn];
struct node{
    int l,r,id;
    friend bool operator < (node x,node y) {
        return x.l/block==y.l/block?x.r<y.r:x.l/block<y.l/block;
    }
}q[mxn];
template <class T>
void rd(T &x){
    x=0;T f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') f = -1 ; c = getchar();}
    while(isdigit(c)) {x = (x<<1) + (x<<3) + (c^48);c = getchar();}
    x*=f;
}
void LOG(){lg[0]=-1;for(int i=1;i<mxn;i++) lg[i]=lg[i>>1]+1;}
void ST(){
    for(int i=1;i<=n;i++) mx[i][0]=a[i] , mn[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
            mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
        }
    }
}
void add(int x){if(++cnt[x]==1) cur++;}
void del(int x){if(--cnt[x]==0) cur--;}
void rmq(int l,int r,int x)
{
    int k=lg[r+1-l];
    int mr = max(mx[l][k],mx[r+1-(1<<k)][k]);
    int ml = min(mn[l][k],mn[r+1-(1<<k)][k]);
    if(mr+1-ml==cur) ans[x] = true;
    else ans[x] = false;
}
int main()
{
    LOG(); rd(t);
    while(t--){
        rd(n) , rd(m) ; block=sqrt(n) ;
        for(int i=1;i<=n;i++)
            rd(a[i]) ,  b[i]=a[i];
        ST();
        sort(b+1,b+1+n);
        int all=unique(b+1,b+1+n)-(b+1);
        for(int i=1;i<=n;i++) 
            a[i]=lower_bound(b+1,b+1+all,a[i])-b;
        for(int i=1;i<=m;i++)
            rd(q[i].l),rd(q[i].r),q[i].id=i;
        sort(q+1,q+1+m);
        int l=1,r=0; cur=0;
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=m;i++){ ///莫队入门
            while(l<q[i].l) del(a[l++]);
            while(l>q[i].l) add(a[--l]);
            while(r<q[i].r) add(a[++r]);
            while(r>q[i].r) del(a[r--]);
            rmq(l,r,q[i].id);
        }
        for(int i=1;i<=m;i++){
            if(ans[i]) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}
神奇的莫队

 

A Hard Allocation

题面:

One day, WNJXYK came out an excellent idea that he could give his friends his special cakes which made of kiwis to eat in parties. But the process of making this kind of special cakes is very complex. One day, his friend Kayaking gave him a formulation which allows WNJXYK to produce one special cake with exact one kiwi in no time. Now let us have a big party over anyone’s imagination.
To simply this question we can assume that WNJXYK invited m friends to his house and he only had n kiwis this time. He wanted to produce special cakes with Kayaking’s formulation and give them to his friends.
Usually, it maybe not possible for people to get exactly same number of cakes in some situations. We can assume that people who received the most one get x cakes and people who received the least get y cakes. WNJXYK wondered that what is the minimal value of |x-y|?

InputThe input starts with one line contains exactly one positive integer T which is the number of test cases.
Each test case contains one line with exactly two positive integer n,m which has been explained above.OutputFor each test case, output one line containing “y” where y is the number of minimal difference.Sample Input

3
5 5
3 10
6 7

Sample Output

0
1
1

Hint

1<=T<=100,1<=n,m<=1000

题解:

比较N个人能否完整分配M个kiwis,如不能就1,反之就0

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
ll n,m,t,k,ans,cnt;
void solve() 
{
    string str ;
    for(cin>>t;t;t--){
        cin>>n>>m;
        if(n%m!=0) cout<<"1\n";
        else cout<<"0\n";
    }    
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

Similar Strings

题面:

Putting two similar strings together will create a very strong power that can quake the earth into parts and the person who did that can be called the Destroyer of the World. In order to stop the Destroyer of the World, WNJXYK decided to check every string in this world to make sure there is no pair of strings are similar. But some strings are too long that WNJXYK cannot judge whether they are similar to others, so he turns to you for help.
Now WNJXYK need you to determine the maximum s, for string A has a substring A’ and string B has a substring B’ whose length are both s and they differ on at most K positions.

InputThe input starts with one line contains exactly one positive integer T which is the number of test cases.
Each test case contains three lines. The first line contains an integer K and each of the following two lines contains a string indicates stringA or stringBOutputFor each test case, output one line containing “y” where y is the maximum s.Sample Input

3
3
qwertypoi
qwetyrio
0
qqqqq
qqqaqqqq
10
qwertyuiop
asdfghjklzxcvbnm

Sample Output

6
4
10

        
 

Hint

1<=T<=5,1<=len(A),len(B)<=4000,0<=K<=min{len(A),len(B)}
Strings only contain lowercase English letters.

题解:

题意是从两个字符串中最长的一段字符串S,S中允许有K个位置的字符不相同,由于字符串的长度最大是4e3,暴力也不会T,就直接尺取长度,计算最值。

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
#define eps 1e-5 
#define open freopen("input.in","r",stdin);freopen("output.in","w",stdout);
int n,m,t,k,ans,cnt;

void calc(char *s1,char *s2)
{
    int l1 = strlen(s1) ;
    int l2 = strlen(s2) ;
    int l = 0 , r = -1 , cnt = 0 ;
    while(l<l1){
        while(cnt<=k && r<l1){
            r++;
            if(s1[r]!=s2[r]) cnt++;
        }
        ans = max(ans , r-l);
        if(s1[l]!=s2[l]) cnt--;
        l++;
    }
}
void solve() 
{
    char s1[mxn] , s2[mxn] ;
    for(cin>>t;t;t--){
        cin>>k>>s1>>s2; ans = 0 ;
        int l1 = strlen(s1) , l2 = strlen(s2);
        for(int i=0;i<l1;i++)
            calc(s1+i,s2);
        for(int i=0;i<l2;i++)
            calc(s2+i,s1);
        cout<<ans<<endl;
    }
}
int main()
{
    /// open
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

 

Flower

题面:

Rabbit loves flowers very much and she plants n pots of flowers in her house. But she never prunes them because she is lazy. So the flowers have different heights and look ugly. One day, Kayaking decides to prune the flowers to make them look beautiful. To make them have equal heights, smart Kayaking has a wonderful idea. Initially, the i-th pot of flower’s height is a[i]. Each time, Kayaking will select n-1 pots of flowers and prune them to make their height subtract 1 with his 49m knife. Exactly, the height of the flowers is at least 1. Now, Kayaking wants to know if it is possible to prune the flowers to make them have equal height. If possible, what is the minimum times he prunes the flowers. Could you tell him?
InputThe input starts with a line contains exactly one positive number T which is the number of test case.Each test case starts with a line contains a number n indicates the number of flowers. Then there is a line contains n numbers indicates a[i].OutputFor each test case, print a single line containing one integer—the minimum times Kayaking prunes the flowers, or -1 if it is impossible.
Sample Input
2
5
1 2 2 2 2
5
1 2 2 2 3
Sample Output
1
-1
Hint
T<=10,n<=10^5,ai<=10^9


题解:

每次选择N-1个数减少一,逆向理解就是任意选择一个数并加一,问经过数轮以后能否使得N个数全部一样,那么,计算出逆向考虑需要的轮次为maxai  - a 1-n ,那么再正向考虑,轮次数如果小于maxai ,那么就可以认为,每次选择N-1个数也可以将所有数变为同一个数

 

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
ll n,m,t,k,ans,cnt;
void solve() 
{
    for(cin>>t;t;t--){
        cin>>n;
        ans = 0 ; k = 0 ; cnt = -1 ;
        for(int i=1;i<=n;i++){
            cin>>k;
            ans += k ;
            cnt = max(cnt,k);
        }    
        if(n*cnt<cnt+ans)
            cout<<abs(ans-n*cnt)<<endl;
        else 
            cout<<-1<<endl;
    }    
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

 

Overflow

 题面:

Kayaking is a naughty boy and he loves to play water. One day, Kayaking finds a bucket. The bottom area of the bucket is S and the height is H. Initially, there is V volume water in the bucket. What makes Kayaking happy is that there are N cube woods beside the bucket. The side length of the i-th cube woods is L[i] and its density is P[i]. Kayaking wants to put all the cube woods to the bucket. And then he will put a cover at the top of the bucket. But CoffeeDog doesn’t allow unless Kayaking can tell CoffeeDog the height of the water in the bucket after Kayaking put all the cuboid woods to the bucket. Could you help him?
It is guaranteed that the cube woods aren’t overlapping. And after putting the wood to the bucket, the bottom of the wood is parallel to the bottom of the bucket.

InputThe first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N denoting the number of cube woods.
Then comes N line. Each line has two real numbers L[i] and P[i].
The last line contains three integers S, H and V.OutputFor each test cases, print a single line containing one real number—the height of the water in the bucket(the number should be rounded to the second digit after the decimal point).Sample Input

1
2
1 1.5
1 0.5
5 100 25

Sample Output

5.30

Hint

T<=10
n<=10^4,P<=6,L<=3,H<=100,L<=H
V,S<=10^7

题解:

在水足够的时候,密度P>=1,则会沉于水面以下,排水体积等于物块体积;密度P<1,则漂浮于水面上方,又因为有盖子,所以可能会有排水的可能性。

在水不足的时候,密度P>=1,则会部分或全部沉于水面下,排水体积小于等于物块体积,密度P<1,则漂浮于水面上,部分物块可能会有排水体积

那么,就可以二分水面高度来计算。

注:题面里有讲“全部放入”,所以不需要考虑叠放问题(憨憨的考虑了物块的底面积于桶底面积的关系)

 

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
#define eps 1e-5 
#define open freopen("input.in","r",stdin);freopen("output.in","w",stdout);
int n,m,t,k,ans,cnt;
double l[mxn] , p[mxn] , s , h , v ;
bool check(double x)
{
    double sum = 0 ;
    for(int i=1;i<=n;i++){
        if(p[i]<1) sum+= p[i]*l[i]*l[i]*l[i];
        else sum+=min(h,l[i])*l[i]*l[i];
    }
    return v+sum < x*s ;
}
void solve() 
{
    scanf("%d",&t);
    for(;t;t--){
        scanf("%d",&n);
        ans = 0 ; k = 0 ; cnt = -1 ;
        for(int i=1;i<=n;i++){
            scanf("%lf %lf",&l[i],&p[i]);
        }
        scanf("%lf %lf %lf",&s,&h,&v);
        double L = v/s , R = h , mid ;
        while(R-L>eps){
            mid = (R+L)/2.0;
            if(check(mid)) R = mid ;
            else L = mid ;
        }
        printf("%.2f\n",L);
    }    
}
int main()
{
    /// open
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

 

The puzzle

 题面:

Kayaking is playing a puzzle game containing n different blocks. He marks the blocks with integers from 1 to n, which show the blocks’ original positions. Each time he can exchange two blocks and he wants to know how many times he needs at least to restore the puzzle.

InputThe input starts with one line contains exactly one positive integer which is the number of test cases.
Each test case contains two lines.
The first line contains an integer, which indicates the number of puzzle pieces.
The second line contains n different integers, the i-th number means the mark of the block in the i-th position.OutputFor each test case, output one line with one number represents the minimum operations.Sample Input

2
4
2 3 4 1
4
2 1 4 3

Sample Output

3
2

Hint

1<=T<=20,1<=n<=100000

题解:

暴力模拟

#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e5+7 ;
#define ll long long
ll n,m,t,k,ans,cnt;
int a[mxn] ;
void solve() 
{
    for(cin>>t;t;t--){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        ans = 0 ;
        while(1){
            int ok = 1 ;
            for(int i=1;i<=n;i++){
                if(i!=a[i]){
                    swap(a[i],a[ a[i] ]);
                    ans++;
                    ok = 0 ;
                }
            }
            if(ok){
                cout<<ans<<endl;
                break;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
View Code

 

 


posted @ 2020-08-07 19:50  __MEET  阅读(901)  评论(0编辑  收藏  举报