Codeforces Round #271 (Div. 2)(dp,线段树good)(很好的一场cf)

很好的一场cf
D. Flowers

We saw the little game Marmot made for Mole's lunch. Now it's Marmot's dinner time and, as we all know, Marmot eats flowers. At every dinner he eats some red and white flowers. Therefore a dinner can be represented as a sequence of several flowers, some of them white and some of them red.

But, for a dinner to be tasty, there is a rule: Marmot wants to eat white flowers only in groups of size k.

Now Marmot wonders in how many ways he can eat between a and b flowers. As the number of ways could be very large, print it modulo 1000000007 (109 + 7).

Input

Input contains several test cases.

The first line contains two integers t and k (1 ≤ t, k ≤ 105), where t represents the number of test cases.

The next t lines contain two integers ai and bi (1 ≤ ai ≤ bi ≤ 105), describing the i-th test.

Output

Print t lines to the standard output. The i-th line should contain the number of ways in which Marmot can eat between ai and bi flowers at dinner modulo 1000000007 (109 + 7).

Sample test(s)
Input
3 2
1 3
2 3
4 4
Output
6
5
5
Note
  • For K = 2 and length 1 Marmot can eat (R).
  • For K = 2 and length 2 Marmot can eat (RR) and (WW).
  • For K = 2 and length 3 Marmot can eat (RRR), (RWW) and (WWR).
  • For K = 2 and length 4 Marmot can eat, for example, (WWWW) or (RWWR), but for example he can't eat (WWWR).

思路:如果i位置为R,则有dp[i-1]种方法,如果为W,则有dp[i-k]种方法

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100010;
const int MOD=1000000007;
int dp[maxn];
int a,b,t,k;
void init()
{
    for(int i=1;i<k;i++)dp[i]=1;
    dp[k]=2;
    for(int i=k+1;i<maxn;i++)
        dp[i]=(dp[i-1]+dp[i-k])%MOD;
    for(int i=1;i<maxn;i++)
        dp[i]=(dp[i-1]+dp[i])%MOD;
}
int main()
{
    scanf("%d%d",&t,&k);
    init();
    while(t--)
    {
        scanf("%d%d",&a,&b);
        printf("%d\n",(dp[b]-dp[a-1]+MOD)%MOD);
    }
    return 0;
}

C. Captain Marmot

Captain Marmot wants to prepare a huge and important battle against his enemy, Captain Snake. For this battle he has n regiments, each consisting of 4 moles.

Initially, each mole i (1 ≤ i ≤ 4n) is placed at some position (xi, yi) in the Cartesian plane. Captain Marmot wants to move some moles to make the regiments compact, if it's possible.

Each mole i has a home placed at the position (ai, bi). Moving this mole one time means rotating his position point (xi, yi) 90 degrees counter-clockwise around it's home point (ai, bi).

A regiment is compact only if the position points of the 4 moles form a square with non-zero area.

Help Captain Marmot to find out for each regiment the minimal number of moves required to make that regiment compact, if it's possible.

Input

The first line contains one integer n (1 ≤ n ≤ 100), the number of regiments.

The next 4n lines contain 4 integers xi, yi, ai, bi ( - 104 ≤ xi, yi, ai, bi ≤ 104).

Output

Print n lines to the standard output. If the regiment i can be made compact, the i-th line should contain one integer, the minimal number of required moves. Otherwise, on the i-th line print "-1" (without quotes).

Sample test(s)
Input
4
1 1 0 0
-1 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-2 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-1 1 0 0
-1 1 0 0
-1 1 0 0
2 2 0 1
-1 0 0 -2
3 0 0 -2
-1 1 -2 0
Output
1
-1
3
3
Note

In the first regiment we can move once the second or the third mole.

We can't make the second regiment compact.

In the third regiment, from the last 3 moles we can move once one and twice another one.

In the fourth regiment, we can move twice the first mole and once the third mole.

直接暴力。。。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=110;
const int INF=1000000000;
int N;
LL dis[10];
struct node
{
    int x,y;
}p[10][4],home[maxn];
LL cal(node a,node b)
{
    LL x=a.x-b.x,y=a.y-b.y;
    return x*x+y*y;
}
void solve()
{
    int ans=INF;
    for(int a=0;a<4;a++)
    {
        for(int b=0;b<4;b++)
        {
            for(int c=0;c<4;c++)
            {
                for(int d=0;d<4;d++)
                {
                    dis[0]=cal(p[1][a],p[2][b]);
                    dis[1]=cal(p[1][a],p[3][c]);
                    dis[2]=cal(p[1][a],p[4][d]);
                    dis[3]=cal(p[2][b],p[3][c]);
                    dis[4]=cal(p[2][b],p[4][d]);
                    dis[5]=cal(p[3][c],p[4][d]);
                    sort(dis,dis+6);
                    //for(int i=0;i<6;i++)cout<<dis[i]<<" ";
                    //cout<<endl;
                    if(dis[0]==0)continue;
                    if(dis[0]==dis[1]&&dis[1]==dis[2]&&dis[2]==dis[3]&&2*dis[3]==dis[4]&&dis[4]==dis[5])
                    {
                        ans=min(ans,a+b+c+d);
                    }
                }
            }
        }
    }
    printf("%d\n",ans==INF?-1:ans);
}
int main()
{
    scanf("%d",&N);
    while(N--)
    {
        for(int i=1;i<=4;i++)
        {
            scanf("%d%d",&p[i][0].x,&p[i][0].y);
            scanf("%d%d",&home[i].x,&home[i].y);
            int x=p[i][0].x-home[i].x,y=p[i][0].y-home[i].y;
            p[i][3].x=home[i].x+y,p[i][3].y=home[i].y-x;
            p[i][2].x=home[i].x-x,p[i][2].y=home[i].y-y;
            p[i][1].x=home[i].x-y,p[i][1].y=home[i].y+x;
        }
        solve();
    }
    return 0;
}

E. Pillars

Marmot found a row with n pillars. The i-th pillar has the height of hi meters. Starting from one pillar i1, Marmot wants to jump on the pillars i2, ..., ik. (1 ≤ i1 < i2 < ... < ik ≤ n). From a pillar i Marmot can jump on a pillar j only if i < j and |hi - hj| ≥ d, where |x| is the absolute value of the number x.

Now Marmot is asking you find out a jump sequence with maximal length and print it.

Input

The first line contains two integers n and d (1 ≤ n ≤ 105, 0 ≤ d ≤ 109).

The second line contains n numbers h1, h2, ..., hn (1 ≤ hi ≤ 1015).

Output

The first line should contain one integer k, the maximal length of a jump sequence.

The second line should contain k integers i1, i2, ..., ik (1 ≤ i1 < i2 < ... < ik ≤ n), representing the pillars' indices from the maximal length jump sequence.

If there is more than one maximal length jump sequence, print any.

Sample test(s)
Input
5 2
1 3 6 7 4
Output
4
1 2 3 5 
Input
10 3
2 1 3 6 9 11 7 3 20 18
Output
6
1 4 6 7 8 9 
Note

In the first example Marmot chooses the pillars 1, 2, 3, 5 with the heights 1, 3, 6, 4. Another jump sequence of length 4 is 1, 2, 4, 5.

思路:刚开始就像怎么维护高度区间内的最长的序列长度是多少,但没有想到用线段树维护。。

首先对高度离散化,然后排序,线段树维护的是此高度所能形成的最长序列的长度和id

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
int N,d,nx;
LL X[maxn],a[maxn];
int dp[maxn],pre[maxn],tmpx;
vector<int> path;
struct IntervalTree
{
    int maxv[maxn<<2];
    int id[maxn<<2];
    void build(){memset(maxv,0,sizeof(maxv));}
    void pushup(int o)
    {
        if(maxv[o<<1]>=maxv[o<<1|1]){maxv[o]=maxv[o<<1];id[o]=id[o<<1];}
        else {maxv[o]=maxv[o<<1|1];id[o]=id[o<<1|1];}
    }
    void update(int o,int l,int r,int pos,int x,int idx)
    {
        if(l==r&&l==pos)
        {
            if(maxv[o]<x)id[o]=idx;
            maxv[o]=max(maxv[o],x);
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update(o<<1,l,mid,pos,x,idx);
        else update(o<<1|1,mid+1,r,pos,x,idx);
        pushup(o);
    }
    int query(int o,int l,int r,int q1,int q2,int &pos)
    {
        if(q1>q2)return 0;
        if(q1<=l&&r<=q2)
        {
            if(maxv[o]>tmpx){pos=id[o];tmpx=maxv[o];}
            return maxv[o];
        }
        int mid=(l+r)>>1;
        int ans=0;
        if(q1<=mid)ans=max(ans,query(o<<1,l,mid,q1,q2,pos));
        if(q2>mid)ans=max(ans,query(o<<1|1,mid+1,r,q1,q2,pos));
        return ans;
    }
}tree;
int find(LL x)
{
    return lower_bound(X+1,X+1+N,x)-X;
}
int main()
{
    scanf("%d%d",&N,&d);
    for(int i=1;i<=N;i++)
    {
        cin>>a[i];
        X[i]=a[i];
    }
    sort(X+1,X+N+1);
    tree.build();
    int ans=0;
    memset(pre,-1,sizeof(pre));
    for(int i=1;i<=N;i++)
    {
        int l=find(a[i]-d);
        if(X[l]!=a[i]-d)l--;
        int r=find(a[i]+d);
        int id1=-1,id2=-1,id3=-1;
        tmpx=-1;
        int len1=tree.query(1,1,N,1,l,id1);
        tmpx=-1;
        int len2=tree.query(1,1,N,r,N,id2);
        id3=(len1<len2?id2:id1);
        int len=max(len1,len2)+1;
        dp[i]=len;
        pre[i]=id3;
        int pos=find(a[i]);
        tree.update(1,1,N,pos,len,i);
    }
    int st=-1;
    for(int i=1;i<=N;i++)
        if(ans<dp[i]){st=i,ans=dp[i];}
    printf("%d\n",ans);
    while(dp[st]!=1)
    {
        path.push_back(st);
        st=pre[st];
    }
    path.push_back(st);
    for(int i=path.size()-1;i>=0;i--)printf("%d ",path[i]);
    printf("\n");
    return 0;
}

F. Ant colony

Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si.

In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He chooses two numbers l and r (1 ≤ l ≤ r ≤ n) and each pair of ants with indices between l and r (inclusively) will fight. When two ants i and j fight, ant i gets one battle point only if si divides sj (also, ant j gets one battle point only if sj divides si).

After all fights have been finished, Mole makes the ranking. An ant i, with vi battle points obtained, is going to be freed only if vi = r - l, or in other words only if it took a point in every fight it participated. After that, Mole eats the rest of the ants. Note that there can be many ants freed or even none.

In order to choose the best sequence, Mole gives you t segments [li, ri] and asks for each of them how many ants is he going to eat if those ants fight.

Input

The first line contains one integer n (1 ≤ n ≤ 105), the size of the ant colony.

The second line contains n integers s1, s2, ..., sn (1 ≤ si ≤ 109), the strengths of the ants.

The third line contains one integer t (1 ≤ t ≤ 105), the number of test cases.

Each of the next t lines contains two integers li and ri (1 ≤ li ≤ ri ≤ n), describing one query.

Output

Print to the standard output t lines. The i-th line contains number of ants that Mole eats from the segment [li, ri].

Sample test(s)
Input
5
1 3 2 4 2
4
1 5
2 5
3 5
4 5
Output
4
4
1
1
Note

In the first test battle points for each ant are v = [4, 0, 2, 0, 2], so ant number 1 is freed. Mole eats the ants 2, 3, 4, 5.

In the second test case battle points are v = [0, 2, 0, 2], so no ant is freed and all of them are eaten by Mole.

In the third test case battle points are v = [2, 0, 2], so ants number 3 and 5 are freed. Mole eats only the ant 4.

In the fourth test case battle points are v = [0, 1], so ant number 5 is freed. Mole eats the ant 4.

思路:题目要求的相当于就是区间内等于区间所有数gcd的数的个数,还是线段树,维护区间所有数的gcd和等于gcd的数的个数

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100010;
int N,M,ans;
int a[maxn];
int gcd(int x,int y)
{
    if(y==0)return x;
    return gcd(y,x%y);
}
struct IntervalTree
{
    int cnt[maxn<<2],g[maxn<<2];
    void build(int o,int l,int r)
    {
        if(l==r)
        {
            cnt[o]=1;
            g[o]=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        pushup(o);
    }
    void pushup(int o)
    {
        int tmp=gcd(g[o<<1],g[o<<1|1]);
        g[o]=tmp;
        if(g[o<<1]==g[o<<1|1]){cnt[o]=cnt[o<<1]+cnt[o<<1|1];}
        else if(tmp==g[o<<1]){cnt[o]=cnt[o<<1];}
        else if(tmp==g[o<<1|1]){cnt[o]=cnt[o<<1|1];}
    }
    int query(int o,int l,int r,int q1,int q2)
    {
        if(q1<=l&&r<=q2)return g[o];
        int mid=(l+r)>>1;
        int x=-1,y=-1;
        if(q1<=mid)x=query(o<<1,l,mid,q1,q2);
        if(q2>mid)y=query(o<<1|1,mid+1,r,q1,q2);
        if(x!=-1&&y!=-1)return gcd(x,y);
        else if(x==-1)return y;
        else return x;
    }
    void query_cnt(int o,int l,int r,int q1,int q2,int x)
    {
        if(q1<=l&&r<=q2)
        {
            if(g[o]==x)ans+=cnt[o];
            return;
        }
        int mid=(l+r)>>1;
        if(q1<=mid)query_cnt(o<<1,l,mid,q1,q2,x);
        if(q2>mid)query_cnt(o<<1|1,mid+1,r,q1,q2,x);
    }
}tree;
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)scanf("%d",&a[i]);
    tree.build(1,1,N);
    scanf("%d",&M);
    while(M--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        int x=tree.query(1,1,N,l,r);
        ans=0;
        tree.query_cnt(1,1,N,l,r,x);
        printf("%d\n",r-l+1-ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值