您的位置:首页 > 其它

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

2016-11-01 18:49 267 查看
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"
#endif
using 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].val
int _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
4000
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"
#endif
using 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"
#endif
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NOIP模拟题 贪心