NOIP模拟题 2016.11.1 [模拟] [贪心] [杂题]
2016-11-01 18:49
267 查看
T1:
题意: 模拟祖玛游戏。。。
没有必要用链表,因为找第几位的时候也是要O(n)走一遍的,不如直接平移。
注意串为空!!
虽然题目说了一开始串中没有可以消除的,但是数据还是有。。
T2:
题意:给一个a[],用栈输出字典序最大的排列。
贪心,每次取a中最大元素和栈顶元素比较即可。
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比较接近。
题意: 模拟祖玛游戏。。。
没有必要用链表,因为找第几位的时候也是要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模拟题 2017.7.3 - 模拟 - 贪心 - 记忆化搜索
- [NOIP模拟题][杂题][贪心][水题]
- 20161010的考试】noip模拟,崩的不要不要的(模拟题,two(three) pointer,模拟
- [vijos NOIP模拟题]天神下凡 贪心+搜索
- (贪心)NOIP模拟题:引爆炸弹
- NOIP模拟题 2016.8.27 [贪心] [DP] [计数问题]
- 【字符串处理】【模拟】【120718测试】【NOIP模拟题】NBA工资
- NOIP2015 day1[tarjan][搜索][模拟][贪心]
- [NOIP模拟][STL][冒泡排序][贪心][Bash模拟]
- 【贪心】CODE[VS] 1063 NOIP2004普及组-合并果子 (刷题记录(模拟+优先队列))
- [NOIp1999 T3] 旅行家的预算(贪心,模拟)
- 【NOIP模拟题】【模拟】【DP】【JOI】2016.11.14第一题 复制&粘贴2 题解
- NOIP模拟题 [模拟][递推][平衡规划]
- 【NOIP模拟赛】【乱搞AC】【贪心】【模拟】匹配
- NOIP模拟题 [暴力][贪心][栈][dfs][找规律]
- NOIP模拟题[贪心][DP][数论]
- NOIP模拟 朋友(快排+贪心)
- jzoj4726. 【NOIP2016提高A组模拟8.22】种花 贪心+堆
- NOIP模拟题 2016.11.16 [模拟] [组合数递推] [数据分治] [Hash]
- 贪心(模拟费用流):NOIP2011 观光公交