NOIP模拟17.9.21

NOIP模拟17.9.21

1 任务安排
manage.in/.out/.cpp
1.1 问题描述
你有N 个工作,同一时刻只能做一个任务, 其中每个工作有其所需时
间, 及完成的Deadline(截止时间), 问要完成所有工作, 最迟要从什么时候开
始。
你最早可以从时间0 开始工作。
1.2 输入格式
第一行一个整数N,表示任务数量
接下来n 行,每行两个整数,Ti; Si,分别表示该任务的持续时间和截
止时间。
1.3 输出格式
输出一个整数,表示最晚的开始时间,如果不能完成,输出-1。
1.4 样例输入
4
3 5
8 14
5 20
1 16
1.5 样例输出
2
1.6 数据规模及约定
对于40% 的数据,N <= 20
对于60% 的数据,N <= 1000
对于100% 的数据,1<= N <= 100000
1<= Ti <= 100000
1<= Si <= 1000000

 

【题解】

水题贪心不解释

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define max(a, b) ((a) > (b) ? (a) : (b))
 7 #define min(a, b) ((a) < (b) ? (a) : (b))
 8 
 9 inline void read(int &x)
10 {
11     x = 0;char ch = getchar(), c = ch;
12     while(ch < '0' || ch > '9')c = ch, ch = getchar();
13     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
14     if(c == '-')x = -x;
15 }
16 
17 const int INF = 0x3f3f3f3f;
18 const int MAXN = 1000000 + 10;
19 
20 struct Node
21 {
22     int s,t;
23 }node[MAXN];
24 
25 bool cmp(Node a, Node b)
26 {
27     return a.t < b.t;
28 }
29 
30 int n;
31 
32 int main()
33 {
34     read(n);
35     for(register int i = 1;i <= n;++ i)
36         read(node[i].s), read(node[i].t);
37     std::sort(node + 1, node + 1 + n, cmp);
38     int begin = node[1].t - node[1].s;
39     int now = node[1].t;
40     for(register int i = 2;i <= n;++ i)
41     {
42         now += node[i].s;
43         if(now > node[i].t)
44         {
45             begin -= now - node[i].t;
46             now = node[i].t;
47         }
48     }
49     printf("%d", max(-1, begin));
50     return 0;
51 }
T1

 

小a 的强迫症
qiang.in/.out/.cpp
2.1 问题描述
小a 是一名强迫症患者,现在他要给一群带颜色的珠子排成一列,现在
有N 种颜色,其中第i 种颜色的柱子有num(i) 个。要求排列中第i 种颜色
珠子的最后一个珠子,一定要排在第i+1 种颜色的最后一个珠子之前。问
有多少种排列珠子的方案。
2.2 输入格式
第一行一个整数N,表示珠子颜色数量
第二行N 个整数,分别表示每种珠子的颜色数量
2.3 输出格式
排列方案数,对998244353 取余
2.4 样例输入
3
2 2 1
2.5 样例输出
3
2.6 数据规模及约定
共3 种排列方案:
1 2 1 2 3
1 1 2 2 3
2 1 1 2 3
对于40% 的数据,所有珠子数量和小于15
对于80% 的数据,N <= 1000,所有珠子数量和小于5000
对于100% 的数据,N <= 100000,所有珠子数量和小于500000

【题解】

一开始想的正解然后马上否定然后推出错误的式子然后挂掉了。

本题有一个很强的限制,叫“排列中第i 种颜色珠子的最后一个

珠子,一定要排在第i+1 种颜色的最后一个珠子之前

不难想递推

num[i]表示第i种珠子颜色

sum[i] = Σnum[1...i]

f[i]表示前i种颜色柱子的方案数

常规思路,对于每一种前i - 1种珠子的放法,考虑第i种珠子怎么放

第i种珠子一定有一颗放到最后面,剩余的num[i] - 1颗可以随便

往前面插。我们可以想成共有sum[i] - 1个空位,选num[i] - 1个空位

放第i种颜色的珠子,其余放已经确定的一种第i - 1种珠子的方法

于是f[i] = f[i - 1] * C(sum[i] - 1,  num[i] - 1)

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define max(a, b) ((a) > (b) ? (a) : (b))
 7 #define min(a, b) ((a) < (b) ? (a) : (b))
 8 
 9 inline void read(long long &x)
10 {
11     x = 0;char ch = getchar(), c = ch;
12     while(ch < '0' || ch > '9')c = ch, ch = getchar();
13     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
14     if(c == '-')x = -x;
15 }
16 
17 const long long INF = 0x3f3f3f3f;
18 const long long MAXN = 100000 + 10;
19 const long long MOD = 998244353;
20 
21 long long n, num[MAXN], sum[MAXN], ans;
22 
23 long long pow(long long a, long long b)
24 {
25     long long r = 1, base = a % MOD;
26     for(;b;b >>= 1)
27     {
28         if(b&1)r *= base, r %= MOD;
29         base *= base, base %= MOD;
30     }
31     return r;
32 }
33 
34 long long f[600000];
35 
36 long long ni(long long a)
37 {
38     if(a == 1)return 1;
39     return pow(a, MOD - 2);
40 } 
41 
42 long long C(long long n, long long m)
43 {
44     if(m > n)return 0;
45     return ((f[n]%MOD * ni(f[m]))%MOD * ni(f[n - m]))%MOD;
46 }
47 
48 int main()
49 {
50     read(n);
51     for(register long long i = 1;i <= n;++ i)
52     {
53         read(num[i]);
54         num[i]%=MOD;
55         sum[i] = sum[i - 1] + num[i];
56         sum[i] %= MOD;
57     }
58     f[0] = 1;
59     for(register long long i = 1;i <= 500000;++ i) f[i] = f[i - 1] * i, f[i] %= MOD;
60     ans = 1;
61     for(register long long i = 2;i <= n;++ i)
62     {
63         ans *= C(sum[i] - 1, num[i] - 1);
64         ans %= MOD;
65     }
66     printf("%lld", ans);
67     return 0;
68 }
T2

 

 

 

3 函数求和
sum.in/.out/.cpp
3.1 问题描述
你有一个含N 个数字的数组A,元素标号1 到N,同时他也有N 个函
数,也标号1 到N。
第i 个函数会返回数组中标号Li 和Ri 之间的元素的和。
现在有以下两种询问:
1 x y 将数组的第x 个元素修改为y。
2 m n 询问标号在m 和n 之间的函数的值的和。
3.2 输入格式
输入数据第一行包含一个整数N,表示数组的长度和函数的数量。
接下来的一行包含N 个整数,表示数组中的元素Ai。
接下来的N 行,每行包含两个整数Li;Ri,表示一个函数。
接下来一行包含一个整数Q,表示询问次数。
下面Q 行,每行一个询问,格式见题目描述。
3.3 输出格式
对于每个第2 类询问,输出相应的答案。
3.4 样例输入
5
1 2 3 4 5
1 3
2 5
4 5
3 5
1 2
4
2 1 4
1 3 7
2 1 4
2 3 5
4
3.5 样例输出
41
53
28
3.6 数据规模及约定
对于前20% 的数据: N  1000;Q  1000
对于另外30% 的数据: Ri 􀀀 Li  10, 所有的x 各不相同
对于100% 的数据: 1  N  105, 1  Li  Ri  N, 1  x  N,
1  m  n  N, 1  Ai; y  109, 1  Q  105

 

【题解】

sb数据结构题去死吧!!!!!

等我做两道分块模板再来切,先贴标称

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cmath>
  5 using namespace std;
  6 typedef unsigned long long LL;
  7 #define lowbit(x) ((x)&-(x))
  8 int n;
  9 int a[100005];
 10 LL c[100005];
 11 int L[100005],R[100005];
 12 int Q;
 13 int t[405][100005];
 14 int belong[100005];// (i-1)/B+1
 15 LL sum[405];
 16 int B,NUM;
 17 void add(int x,LL d){
 18     while(x<=n){
 19         c[x]+=d;
 20         x+=lowbit(x);
 21     }
 22 }
 23 LL ask(int x){
 24     LL ret=0;
 25     while(x){
 26         ret+=c[x];
 27         x-=lowbit(x);
 28     }
 29     return ret;
 30 }
 31 int main(){
 32     freopen("sum.in","r",stdin);
 33     freopen("sum.out","w",stdout);
 34     scanf("%d",&n);
 35     for(int i=1;i<=n;i++){
 36         scanf("%d",&a[i]);
 37     }
 38     for(int i=1;i<=n;i++){
 39         scanf("%d%d",&L[i],&R[i]);
 40     }
 41     B=sqrt(n)+1;
 42 //  printf("#%d\n",B);
 43     NUM=(n-1)/B+1;
 44     for(int i=1;i<=n;i++) belong[i]=(i-1)/B+1;
 45     for(int i=1;i<=n;i++) c[i]=a[i];
 46     for(int i=1;i<=n;i++){
 47         if(i+lowbit(i)<=n){
 48             c[i+lowbit(i)]+=c[i];
 49         }
 50     }
 51     for(int i=1;i<=n;i++){
 52         t[belong[i]][L[i]]++;
 53         t[belong[i]][R[i]+1]--;
 54     }
 55     for(int i=1;i<=NUM;i++){
 56         for(int j=1;j<=n;j++){
 57             t[i][j]+=t[i][j-1];
 58             sum[i]+=t[i][j]*1ULL*a[j];
 59         }
 60     }
 61     scanf("%d",&Q);
 62     while(Q--){
 63         int type,x,y;
 64         scanf("%d%d%d",&type,&x,&y);
 65         if(type==1){
 66             for(int i=1;i<=NUM;i++){
 67                 sum[i]-=t[i][x]*1ULL*a[x];
 68                 sum[i]+=t[i][x]*1ULL*y;
 69             }
 70             add(x,-a[x]);
 71             a[x]=y;
 72             add(x,a[x]);
 73         }else{
 74             int Ln,Rn;
 75             Ln=belong[x],Rn=belong[y];
 76             LL ans=0;
 77             if(Ln==Rn){
 78                 for(int i=x;i<=y;i++){
 79                     ans+=ask(R[i])-ask(L[i]-1);
 80                 }
 81             }else{
 82                 for(int i=Ln+1;i<Rn;i++) ans+=sum[i];
 83                 int lim;
 84                 lim=Ln*B;
 85                 lim=min(lim,y);
 86                 for(int i=x;i<=lim;i++){
 87                     ans+=ask(R[i])-ask(L[i]-1);
 88                 }
 89                 lim=(Rn-1)*B+1;
 90                 lim=max(lim,x);
 91                 for(int i=lim;i<=y;i++){
 92                     ans+=ask(R[i])-ask(L[i]-1);
 93                 }
 94             }
 95             printf("%llu\n",ans);
 96         }
 97     }
 98     fclose(stdout);
 99     return 0;
100 }
T3

 

posted @ 2017-09-22 21:51  嘒彼小星  阅读(337)  评论(0编辑  收藏  举报