首页 > 代码库 > Poj3145Harmony Forever线段树+鸽巢原理

Poj3145Harmony Forever线段树+鸽巢原理

  小数据直接暴力,大数据查找0-mod — 1,mod — 2*mod-1,2*mod — 3*mod-1.....

因为 n%mod 的范围<=n-1 ,所以k*mod — (k+1)*mod之间%mod的最小值 应该是 k*mod — (k+1)*mod-1之间的最小值,如果存在的话,用线段树维护下区间最值就好了,有个地方得注意下。

#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<vector>#include<stdlib.h>using namespace std;typedef long long LL;#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1const int maxn = 1000000 + 1000;int sum[maxn << 2];const int INF = 1<<30;int ncnt;int val[maxn];int pos[maxn];void up(int rt){    sum[rt] = min(sum[rt << 1], sum[rt << 1 | 1]);}void build(int l, int r, int rt){    sum[rt] = INF;    if (l == r){        return;    }    int mid = (l + r) >> 1;    build(lson);    build(rson);    up(rt);}void update(int key, int l, int r, int rt){    if (l == r){        sum[rt] = key; return;    }    int mid = (l + r) >> 1;    if (key <= mid) update(key, lson);    else update(key, rson);    up(rt);}int ask(int L, int R, int l, int r, int rt){    if (L <= l&&r <= R) return sum[rt];    int ans = INF;    int mid = (l + r) >> 1;    if (L <= mid) ans = min(ans, ask(L, R, lson));    if (R > mid) ans = min(ans, ask(L, R, rson));    return ans;}void gao(int x){    int Min = INF; int ans=INF;    for (int i = ncnt - 1; i >= 1; i--){        if (val[i] % x == 0) {            printf("%d\n", i); return ;        }        if (val[i] % x < Min){            Min = val[i] % x;            ans = i;        }    }    printf("%d\n", ans);}void gao1(int x){    int l = 0; int r = x - 1; int ans = -1;//刚开始初始为INF 挂了一晚上,因为他后面要取模不能直接 拿这个ans%x 与temp%x比较    while (l <= maxn){        if (r > maxn) r = maxn;        int temp = ask(l, r, 0, maxn, 1);        if(temp!=INF){        if (ans==-1||temp%x < ans%x) ans = temp;        else if (temp%x == ans%x&&pos[temp]>pos[ans])            ans = temp;        }        l += x; r += x;    }    printf("%d\n", pos[ans]);}int main(){    char str[100];    int k;    int cnt = 0;    int T;    while (scanf("%d",&T),T){        if(cnt) puts("");        ncnt = 1;        build(0, maxn, 1);        printf("Case %d:\n", ++cnt);        while (T--){            scanf("%s%d", str, &k);            if (str[0] == B){                val[ncnt] = k;                pos[k] = ncnt++;                update(k, 0, maxn, 1);            }            else{                if(ncnt==1){                    printf("-1\n");                }                else                if (k < 10000) gao(k);                else gao1(k);            }        }    }    return 0;}

 

Poj3145Harmony Forever线段树+鸽巢原理