AtCoder Regular Contest 068 E- Snuke Line

http://www.elijahqi.win/2017/12/20/arc-e-snuke-line/
Time limit時間制限 : 2sec / Memory limitメモリ制限 : 256MB
配点 : 700 点
問題文
すぬけくんは鉄道会社を運営するゲームで遊ぶことにしました。すぬけ鉄道には M+1 個の駅があり、 0 から M までの番号がついています。 すぬけ鉄道の列車は駅 0 から d 駅ごとに停車します。 例えば d=3 のとき駅 0,駅 3,駅 6,駅 9, … に停車します。
すぬけ鉄道が走っている地域には N 種類の名産品があり、種類 i の名産品は 駅 li,駅 li+1,駅 li+2, …, 駅 ri のいずれかに列車が停車したとき購入することが可能です。
列車が停車する間隔 d は 1,2,3,…,M の M 種類が存在しています。 M 種類の列車それぞれについて、その列車に駅 0 で乗車した場合に購入可能な名産品の種類数を求めなさい。 なお、列車から別の列車への乗り換えは許されないものとします。
制約
● 1≦N≦3×105
● 1≦M≦105

● 1≦li≦ri≦M

入力
入力は以下の形式で標準入力から与えられる。
N M
l1 r1
:
lN rN

出力

答えを M 行に出力せよ。 i 行目では i 駅ごとに停車する列車に乗った場合に購入可能な名産品の種類数を出力せよ。

入力例 1
Copy
3 3
1 2
2 3
3 3

出力例 1
Copy
3
2
2

● 1 駅ごとに停車する列車に乗った場合、種類 1,2,3 の 3 種類の名産品を購入することが可能です。
● 2 駅ごとに停車する列車に乗った場合、種類 1,2 の 2 種類の名産品を購入することが可能です。

● 3 駅ごとに停車する列車に乗った場合、種類 2,3 の 2 種類の名産品を購入することが可能です。

入力例 2
Copy
7 9
1 7
5 9
5 7
5 9
1 1
6 8
3 4

出力例 2
Copy
7
6
6
5
4
5
5
3
2

Score : 700 points
Problem Statement
Snuke has decided to play a game, where the player runs a railway company. There are M+1 stations on Snuke Line, numbered 0 through M. A train on Snuke Line stops at station 0 and every d-th station thereafter, where d is a predetermined constant for each train. For example, if d=3, the train stops at station 0, 3, 6, 9, and so forth.
There are N kinds of souvenirs sold in areas around Snuke Line. The i-th kind of souvenirs can be purchased when the train stops at one of the following stations: stations li, li+1, li+2, …, ri.
There are M values of d, the interval between two stops, for trains on Snuke Line: 1, 2, 3, …, M. For each of these M values, find the number of the kinds of souvenirs that can be purchased if one takes a train with that value of d at station 0. Here, assume that it is not allowed to change trains.
Constraints
● 1≦N≦3×105
● 1≦M≦105

● 1≦li≦ri≦M

Input
The input is given from Standard Input in the following format:
N M
l1 r1
:
lN rN

Output

Sample Input 1
Copy
3 3
1 2
2 3
3 3

Sample Output 1
Copy
3
2
2

● If one takes a train stopping every station, three kinds of souvenirs can be purchased: kind 1, 2 and 3.
● If one takes a train stopping every second station, two kinds of souvenirs can be purchased: kind 1 and 2.

● If one takes a train stopping every third station, two kinds of souvenirs can be purchased: kind 2 and 3.

Sample Input 2
Copy
7 9
1 7
5 9
5 7
5 9
1 1
6 8
3 4

Sample Output 2
Copy
7
6
6
5
4
5
5
3
2

题目要求:我们从0开始每次增加k的长度 然后 询问这些点一共可以得到多少纪念品 这个纪念品 每次是一个区间
那么我们 可以每次枚举这个长度k 当然k==1的时候 直接输出n即可
然后每次枚举这个长度k 然后查询 l+1~r-1之间一共有多少区间 然后能买到纪念品的地方不就是总的区间-不可能包含的区间数 输出即可 这个不可能包含的区间数其实就是我可以看成二维数点 然后左端点看成(l,l)(r,r)然后数一下这个矩形内有多少点即可 主席树可实现

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 330000
using namespace std;
inline char gc(){
    /*static char now[1<<16],*T,*S;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;*/return getchar();
}
inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
struct node{
    int l,r;
}line[N];
inline bool cmp(node a,node b){return a.l<b.l;}
struct node1{
    int left,right,v;
}tree[N*20];
int num,n,m,root[N];
inline void insert1(int &x,int l,int r,int p){
    tree[++num]=tree[x];x=num;tree[x].v++;if (l==r) return;
    int mid=l+r>>1;if (p<=mid) insert1(tree[x].left,l,mid,p);else insert1(tree[x].right,mid+1,r,p);
}
inline int query(int rt1,int rt2,int l,int r,int l1,int r1){
    if (l1<=l&&r1>=r) return tree[rt2].v-tree[rt1].v;
    int mid=l+r>>1;int tmp=0;if (l1<=mid) tmp+=query(tree[rt1].left,tree[rt2].left,l,mid,l1,r1);
    if (r1>mid) tmp+=query(tree[rt1].right,tree[rt2].right,mid+1,r,l1,r1);return tmp;
}
int main(){
    freopen("arc.in","r",stdin);
    n=read();m=read();
    for (int i=1;i<=n;++i) line[i].l=read(),line[i].r=read();
    sort(line+1,line+n+1,cmp);int tot=0;printf("%d\n",n);
    for (int i=1;i<=m;++i){root[i]=root[i-1];
    while(line[tot+1].l==i) insert1(root[i],1,m,line[tot+1].r),++tot;}
    for (int len=2;len<=m;++len){
        int j=len,tmp=0,now=m%len;now=m-now;
        for (;j<=m;j+=len) tmp+=query(root[j-len],root[j-1],1,m,j-len+1,j-1);
        if(now<m) tmp+=query(root[now],root[m],1,m,now+1,m);
        printf("%d\n",n-tmp);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值