[Fill file] noip2019 training test events (eight)

Problem B: 2048

Special Judge

Time Limit: 1000 ms Memory Limit: 256 MB

Description

2048 was once a popular global game.

Today, we have a different way to play this game.

Now, you have a double-ended queue, you can only elements from the left or from the right into the double-ended queue. Once placed shall not be removed. After placed, if there are two consecutive identical elements in the queue, they are automatically merged into a new element - the original and the two elements. If the same new element to its adjacent elements, continued consolidation ......

Such as: deque have 2, 4, 16 three elements. If 2 is inserted from the left end deque, the queue becomes 8, 16. If 2 is inserted from the right end of the deque, the queue will become 2, 4, 16, 2.

Beginning, deque is empty. We'll give you some numbers, you need to turn inserted into the double-ended queue. Asked if there is a program of operation, such that the deque last only a few.

Input

A first line integer T, denotes the number of data sets.

For each set of test data:

The first line an integer n, the number represents the number we give you.

The next line number n, mean that we give you the number ai. These numbers are non-negative integer power of 2, i.e., for each i there is an integer k satisfies k≥0 and ai = 2 ^ k.

Output

For each set of data, so that if there is a program operating deque last only a few, output no. Otherwise, the output of a string of length n, wherein if the i-th inserted from left to deque, the i-th character is L; if the i-th inserted from right to deque, the i-th characters r.

Sample Input
3
9
2 8 4 1 1 4 4 4 4
5
2 16 4 8 2
3
2 2 2

Sample Output

rrrlllrrr
no
no

HINT

Sample 1 explanation

1, 2 is inserted from the right side, it becomes deque 2

2, is inserted from the right 8, 28 becomes the deque

3, 4 is inserted from the right side, the deque to become 284

4, inserted from the left one, becomes the deque 1284

5, 1 is inserted from the left, the deque to become 484

6, 4 is inserted from the left, the deque to become 164

7, 4 is inserted from the right side, the deque to become 168

8, inserted from the right 4, the deque to become 1684

9, 4 is inserted from the right side, it becomes deque 32

Data range and Conventions

For 20% of the data, n≤19, T≤100

For all data, 1≤n≤1000, a1 ~ an, and no more than 2 ^ 13, T≤10000, wherein the data n> 20 is not more than 150 groups.

Solution

Consider pressure-like search +

L represents a click with the left half of the current state, then the right half of the prefix can be represented by L and subtracting pretreated

If you want to join the current number smaller than L, lowbit, then left to join

Similarly the right part

Then a vis said about the current state has not been searched. Since the maximum is only 8192, so the array is in bloom.

For L and R of a state, if highbit (L) <= highbit (R), then put highbit (R) combined to the left, so that the right and left merged completed

Fine I understand (though I speak unclear)

#include<bits/stdc++.h>
using namespace std;
#define R (sum[x]-L)
#define lowbit(x) x&-x
int n;
int a[10001];
bool flag;
int vis[1010][8195];
bool ans[10001];
int sum[10001];
int highbit[10001];
int sb;
void solve(int x,int L){
    //cout<<x<<" "<<L<<endl;
    if(highbit[L]<=highbit[R])L+=highbit[R];
    if(vis[x][L]==sb)return;
    vis[x][L]=sb;
    if(x==n){
        //cout<<L<<" "<<(lowbit(L))<<endl;
        if(L==(lowbit(L)))flag=true;
        return;
    }
    int xx=x+1;
    int l=(lowbit(L)),r=(lowbit(R));
    if(a[xx]<=l)ans[xx]=0,solve(xx,L+a[xx]);
    if(flag)return;
    if(!r||a[xx]<=r)ans[xx]=1,solve(xx,L);
}
void init(){
    for(int i=2;i<=8192;++i)highbit[i]=highbit[i>>1]+1;
    for(int i=1;i<=8192;++i)highbit[i]=1<<highbit[i];
}
void print(){
    for(int i=1;i<=n;++i){
        putchar((ans[i]?'r':'l'));
    }
    putchar('\n');
}
int main(){
    int T;
    scanf("%d",&T);
    //T=1;
    init();
    while(T--){
        memset(sum,0,sizeof(sum));
        memset(ans,0,sizeof(ans));
        flag=false;
        sb++;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        //cout<<sum[n]<<endl;
        if(sum[n]!=(lowbit(sum[n]))){
            puts("no");
            continue;
        }
        solve(1,a[1]);
        if(flag){
            print();
        }
        else puts("no");
    }
}

Problem C: Subsequence Count

Time Limit: 1000 ms Memory Limit: 256 MB

Description

Given a string S1 ⋯ n 01 and Q operations.

There are two types of operations:

1, the number of [l, r] negated interval (therein becomes 0 becomes 0 1,1).

2, the query string S substring Sl ⋯ r the number of different sequences. Since the answer may be large, please answer of 10 ^ 9 + 7 modulo.

In mathematics, the subsequence is a sequence from the initial relative position of the sequence without destroying the elements by removing some of the remaining elements (preceding or following) formed by the new sequence.

Input

The first line contains two integers N and Q, respectively, and a string length number of operations.

The second line contains a string S.

Next Q lines of type integer of 3, l, r, wherein the type represents the type of operation, l, r represents the operation interval [l, r].

Output

For each inquiry type = 2, the output of a integer answer. Since the answer may be large, please answer of 10 ^ 9 + 7 modulo.

Sample Input
4 4
1010
2 1 4
2 2 4
1 2 3
2 1 4

Sample Output

11
6
8

HINT

For 5% of data, N≤20, Q = 1

For 10% of the data, N≤1000, Q = 1

For 20% of the data, N≤10 ^ 5, Q≤10

For another 30% of the data, 1≤N≤10 ^ 5,1≤Q≤10 ^ 5, type = 2

To 100% of the data, 1≤N≤105,1≤Q≤105

Solution

We use the number string Qiuzi dp, dp set [i] [0/1], representative of the i-th bit dp, the number of a few to the end of the substring 0/1

Have

\(dp[i][s[i]]=dp[i-1][s[i]]+dp[i-1][!s[i]]+1,dp[i][!s[i]]=dp[i-1][!s[i]]\)

Then turn in a matrix:

\[ if(s[i]==0)\left[ \begin{matrix} 1 & 0 & 0 \\ 1 & 1 & 0 \\ dp[i][0] & dp[i][1] & 1 \\ \end{matrix} \right] \]

\[ if(s[i]==1)\left[ \begin{matrix} 1 & 1 & 0 \\ 0 & 1 & 0 \\ dp[i][0] & dp[i][1] & 1 \\ \end{matrix} \right] \]

Then each query word is for a range of matrix multiplication up, it sets a segment tree maintenance

If that is to reverse the interval 0,1, then directly to the matrix elements to exchange a few good position

I could write ugly, 990ms rubbing his time in the past, when the examination is often the QAQ card

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod (long long)(1e9+7)
int read(){
    int num=0;
    char ch=getchar();
    while(!isdigit(ch)){
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num;
}
ll write(ll x){
    if(x<0){putchar('-');x=~(x-1);}
    ll s[20],top=0;
    while(x){s[++top]=x%10;x/=10;}
    if(!top)s[++top]=0;
    while(top)putchar(s[top--]+'0');
    putchar('\n');
}
struct matrix{
    ll a[3][3];
    matrix(){a[0][1]=a[0][2]=a[1][0]=a[1][2]=a[2][0]=a[2][1]=0;a[0][0]=a[1][1]=a[2][2]=1;}
};
matrix operator *(matrix a,matrix b){
    matrix c;
    memset(c.a,0,sizeof(c.a));
    for(int i=0;i<3;++i){
        for(int j=0;j<3;++j){
            for(int k=0;k<3;++k){
                c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
            }
        }
    }
    return c;
}
matrix val[400001];
int tag[400001];
char a[200001];
void build(int o,int l,int r){
    if(l==r){
        if(a[l]=='0'){
            val[o].a[1][0]=val[o].a[2][0]=1;
        }
        else val[o].a[0][1]=val[o].a[2][1]=1;
        return;
    }
    int mid=(l+r)/2;
    build(o*2,l,mid);
    build(o*2+1,mid+1,r);
    val[o]=val[o*2]*val[o*2+1];
}
void swaps(matrix &a){
    swap(a.a[0][0],a.a[0][1]);
    swap(a.a[1][0],a.a[1][1]);
    swap(a.a[2][0],a.a[2][1]);
    swap(a.a[0][0],a.a[1][0]);
    swap(a.a[0][1],a.a[1][1]);
}
void pushdown(int o){
    if(tag[o]){
        swaps(val[o*2]),swaps(val[o*2+1]);
        tag[o*2]^=1,tag[o*2+1]^=1;
        tag[o]=0;
    }
}
void update(int o,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        tag[o]^=1;
        swaps(val[o]);
        return;
    }
    pushdown(o);
    int mid=(l+r)/2;
    if(L<=mid)update(o*2,l,mid,L,R);
    if(mid<R)update(o*2+1,mid+1,r,L,R);
    val[o]=val[o*2]*val[o*2+1];
}
matrix query(int o,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        return val[o];
    }
    pushdown(o);
    int mid=(l+r)/2;
    matrix ret;
    if(L<=mid)ret=ret*query(o*2,l,mid,L,R);
    if(mid<R)ret=ret*query(o*2+1,mid+1,r,L,R);
    return ret;
}
int main(){
    int n,m;
    scanf("%d%d%s",&n,&m,a+1);
    build(1,1,n);
    while(m--){
        int opt=read(),l=read(),r=read();
        if(opt==1){
            update(1,1,n,l,r);
        }
        else {
            matrix tmp=query(1,1,n,l,r);
            write((tmp.a[2][1]+tmp.a[2][0])%mod);
        }
    }
}

Guess you like

Origin www.cnblogs.com/youddjxd/p/11442067.html