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
【题解】
水题贪心不解释
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
小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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
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数据结构题去死吧!!!!!
等我做两道分块模板再来切,先贴标称
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }