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
#include
#include
#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.lint 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(nownow],root[m],1,m,now+1,m);
        printf("%d\n",n-tmp);
    }
    return 0;
}

你可能感兴趣的:(主席树)