NOIP模拟题 2016.11.1 [模拟] [贪心] [杂题]

来源:互联网 发布:淘宝金酷娃玩具扫地车 编辑:程序博客网 时间:2024/06/05 01:18

T1:
题意: 模拟祖玛游戏。。。
没有必要用链表,因为找第几位的时候也是要O(n)走一遍的,不如直接平移。
注意串为空!!
虽然题目说了一开始串中没有可以消除的,但是数据还是有。。

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<set>#include<string>#include<iomanip>#include<ctime>#include<climits>#include<cctype>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;#define smax(x,tmp) x=max((x),(tmp))#define smin(x,tmp) x=min((x),(tmp))#define maxx(x1,x2,x3) max(max(x1,x2),x3)#define minn(x1,x2,x3) min(min(x1,x2),x3)const int INF=0x3f3f3f3f;const int maxn = 2005;inline int idx(char ch) { return ch - 'A' + 1; }struct Node{    int pre,nxt;    int val;}node[maxn];int maxnode;#define pre(x) node[x].pre#define nxt(x) node[x].nxt#define val(x) node[x].valint _begin,_end;queue <int> que;inline int require(){    int root;    if(!que.empty()) root=que.front(),que.pop();    else root = ++maxnode;    return root;}inline void recycle(int root){    pre(root)=nxt(root)=0;    val(root)=0;    que.push(root);}char s[maxn];int T;void init(){    scanf("%s",s);    if(s[0]>='0' && s[0]<='9')    {        sscanf(s,"%d",&T);        return;    }    int lens = strlen(s);    for(int i=3;i<lens+3;i++)    {        int d = idx(s[i-3]);        pre(i) = i-1;        nxt(i) = i+1;        val(i) = d;    }    _begin=1; _end=2; maxnode=lens+2;    pre(3)=_begin; nxt(maxnode)=_end;    nxt(_begin)=3; pre(_end)=maxnode;}int find(int rank){    int root = _begin;    int tot = 0;    while(tot < rank) root=nxt(root),tot++;    return root;}void update(int root){    if(root == _begin || root == _end) return;    int t1=0,t2=0;    int x = root;    while(val(pre(x)) == val(root)) x = pre(x), t1++;    int y = root;    while(val(nxt(y)) == val(root)) y = nxt(y), t2++;    if(t1+t2+1<3) return;    x = root; y = nxt(root);    int d = val(root);    while(val(x) == d) x=pre(x),recycle(nxt(x));    while(val(y) == d) y=nxt(y),recycle(pre(y));    nxt(x)=y; pre(y)=x;    update(x);}void insert(int pos,int d){    int t1 = find(pos);    int t2 = nxt(t1);    int now = require();    pre(now)=t1; nxt(now)=t2;    nxt(t1)=now; pre(t2)=now;    val(now) = d;    update(now);}void print(){    int root = nxt(_begin);    if(root == _end)    {        putchar('-');        return;    }    while(root ^ _end)    {        putchar(val(root)+'A'-1);        root = nxt(root);    }}void work(){    if(!T) scanf("%d",&T);    while(T--)    {        int pos;        char ch;        scanf("%d %c",&pos,&ch);        insert(pos,idx(ch));        print();        putchar('\n');    }}int main(){    freopen("hao.in","r",stdin);    freopen("hao.out","w",stdout);    init();    work();    return 0;}

T2:
题意:给一个a[],用栈输出字典序最大的排列。
贪心,每次取a中最大元素和栈顶元素比较即可。

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<set>#include<string>#include<iomanip>#include<ctime>#include<climits>#include<cctype>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;#define smax(x,tmp) x=max((x),(tmp))#define smin(x,tmp) x=min((x),(tmp))#define maxx(x1,x2,x3) max(max(x1,x2),x3)#define minn(x1,x2,x3) min(min(x1,x2),x3)template <class T> inline void read(T &x){    x = 0;    T flag = 1;    char ch = (char)getchar();    while(ch<'0' || ch>'9')    {        if(ch == '-') flag = -1;        ch = (char)getchar();    }    while(ch>='0' && ch<='9')    {        x = (x<<1) + (x<<3) + ch - '0';        ch = (char)getchar();    }    x *= flag;}const int INF=0x3f3f3f3f;const int maxn = 1000005;bool used[maxn];int n;int a[maxn];stack <int> sta;int main(){    freopen("kun.in","r",stdin);    freopen("kun.out","w",stdout);    read(n);    for(int i=1;i<=n;i++) read(a[i]);    int MAX = n;    int pos = 1;    while(true)    {        while(used[MAX]) MAX--;        if(!MAX)        {            while(!sta.empty()) printf("%d ",sta.top()),sta.pop();            break;        }        if(sta.empty() || MAX>sta.top())        {            while(a[pos]^MAX) sta.push(a[pos]),used[a[pos]]=true,pos++;            used[MAX] = true; pos++;            printf("%d ",MAX);        }        else while(!sta.empty() && sta.top()>MAX) printf("%d ",sta.top()),sta.pop();    }    return 0;}

T3:
题意:我们 有一个序列 ,现在他里面有三个数 1,2,2。我们从第三个数开始考虑:
1、第三个数是 2,所以我们在序列后面写 2个3,变成 1,2,2,3,3。
2、第四个数是 3,所以我们在序列后面写 3个4,变成 1,2,2,3,3,4,4,4。
那么你可以看到 ,这个序列应该是 1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…。
如果设last(x)表示x最后出现的位置,求last(last(x))。

分析:
找规律,把last(last(x))的差分序列找出来,可以发现规律,每一个数就是a[block]*i,a[block]是第一个乘数,i是从x。
分块加速处理。
a[i]大概在1300000的时候和1e9比较接近。

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<set>#include<string>#include<iomanip>#include<ctime>#include<climits>#include<cctype>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else#define AUTO "%lld"#endifusing namespace std;#define smax(x,tmp) x=max((x),(tmp))#define smin(x,tmp) x=min((x),(tmp))#define maxx(x1,x2,x3) max(max(x1,x2),x3)#define minn(x1,x2,x3) min(min(x1,x2),x3)typedef long long LL;const int mod = 1000000007;const int N = 1400000;const int maxn = N + 10;int a[maxn];LL sum[maxn],ANS[maxn];void pre_work(){    a[1]=1; a[2]=a[3]=2;    LL last = 3;    int cur = 3;    while(true)    {        for(int i=last+1;i<=last+a[cur];i++) a[i] = cur;        last += a[cur];        cur++;        if(last+a[cur]>N) break;    }    for(int i=1;i<=N;i++) sum[i]=sum[i-1]+a[i];    last = 0;    for(int i=1;i<=N;i++)    {        LL L = last + 1;        LL R = last + a[i];        ANS[i] = ((LL)a[i]*((LL)L+R)/2)%mod * i %mod;        (ANS[i] += ANS[i-1]) %=mod;        last = R;    }}void work(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        int cur_i = upper_bound(sum+1,sum+N+1,n) - sum - 1;        LL ans = ANS[cur_i];        if(sum[cur_i]<n)        {            LL len = n-sum[cur_i];            LL L = sum[cur_i] + 1;            LL R = sum[cur_i] + len;            cur_i++;            ans += ((LL)len*((LL)L+R)/2)%mod * cur_i %mod;            ans %= mod;        }        printf(AUTO"\n",ans);    }}int main(){    freopen("nan.in","r",stdin);    freopen("nan.out","w",stdout);    pre_work();    work();    return 0;}
0 0
原创粉丝点击