codeforces.R174题解全
http://codeforces.com/contest/283/
虽然比赛中还是犯了两个很2的错误,但是还是顺利升回红色id了=。=~。。D题推导中连续整数和竟然写少了个2~,e题读错题了。。悲剧啊
A.比较简单,操作时候一直维护总和就可以了。。对于操作1(前a个数全部增加x)以及操作2(添加一个新数字在队列最后)显然可以顺利做到,而操作3则要求求出当前队列最后数字的值,我们可以用lasy的思想处理操作1即可以,如在head ~head+a 的位置增加x,我们可以在head+a的位置记录这个x(mark[head+ai]+=x),当head+a被删除之后后,才会要求求出head+ai-1位置的值,所以在删除head+a后我们将记录在该位置上的x值传到上一位即可(mark[head+a-1] += mark[head+a])..时间空间复杂度均O(n)
B.记忆化搜索,对于每个x值,其下面两种可能操作,x+=a[x] , x-=a[x]。。故总共只有O(n*2)种状态,这里用dp[i][0]表示x=i,下一次操作x变化为i-a[i], dp[i][1]表示x=i,下一次操作x变化为i+a[i]...预处理dp[2~n][0],即可以回答所有询问,ps:当i-a[i] == 1时,此时将陷入死循环dp[i][0]=-1.时间空间复杂度均为O(n).
C.预处理+dp..由于题目中对于硬币数量约束条件有该限制:It is known that all bi are distinct and all ci are distinct.。。故可以硬币数量约束条件必将构成链或者环关系。。显然环意味着无解,对于链关系Ai1 < Ai2 < Ai3 < Ai4 < Ai5...< Ain(Ai表示硬币数量 ,Bi表示硬币价值),则其总价值可以表示成如下关系:
Ai1Bi1+Ai2Bi3+..+AinBin= Ai1(Bi1+Bi2+Bi3+..Bin) + (Ai2-Ai1)Bi2+...+(Ain-Ai1)Bin
=Ai1(Bi1+Bi2+...+Bin) + (Ai2-Ai1)(Bi2+..+Bin)+(Ai3-Ai2)(Bi3+...+Bin) +..+(Ain-Ain-1)Bin
此时我们可以设 a'i = (Ai-Ai-1) b'i = (Bi+..+Bin);并令总价值tol = tol - (b'i2+..b'in) 此时问题于原问题等价,但是没有了任何硬币数量约数。。所以预处理完当成普通无限多重背包处理即可。
D.dp...
首先要求分析何种情况下x能表示成y个连续整数的和,显然y个连续整数和可以表示成(2k+y+1)*y/2..分情况讨论,当y为奇数时,显然(2k+y+1)/2可以等于任意整数,故此时的充要条件为y是x的因子即x%y==0; 当y为偶数时,(2k+y+1)为任意奇数,y/2必须是x的因子,且x/(y/2)为奇数,故如果我们用2^k*A(A%2==1)来表示x,则可以此时y=2^(k+1)*B,B为A的因子。。
综上,有结论当x=2kA(A%2==0)y取值集合为{A的因子}υ {A的因子}*2k+1
之后的dp过程则异常简单,dp[i]表示当第i个数不改变时候,使得前i个数满足题目的序列要求的最小代价。。转移则枚举j<i,假设j是i之前上一个不改变的位置,判断改变j+1~i-1位置上的数字均改变后能否使得构成满足题目要求序列,显然j+1~i-1的改变是可以贪心进行的,w[j] = 2ba..有上结论可以知因子a显然保留下来更优,故w[j+1] = a或者2b+1a。。如果w[j] = 2b[j]a[j] ,w[i] = 2b[i]a[i],满足a[j]%a[i]==0 && (b[j]+i-j == b[i] || b[i]<=i-j-1),时我们必然有方法构造j+1~i-1使得序列满足要求。。
E.线段树。。
首先考虑一个子问题如何统计题目要求的三元组个数,此处有一非常经典解法求不满足要求的三元组个数,设三元组(a1,a2,a3)不满足要求,则必然且只有一个ai大于其他两个。。设wi表示比i强的奶牛数目,则答案为 n*(n-1)*(n-2)/6 - Σwi(wi-1)/2 ...
之后考虑如何求wi数目,如果没有题目中出现的翻转操作,结果将如下,00000011111111 i左边的奶牛均为0表示其若于i,i右边奶牛均为1表示则其强于1.。之后考虑翻转区间ak,bk ,如i<ak该操作不会对wi结果造成任何影响,直到i>=ak此时我们可以将ak~bk的位置的01值翻转(基本的线段树操作),直到i>bk,此时该区间再次不会对wi结果产生影响,我们再执行一遍ak~bk位置01值翻转即可。。至此我们得到了一个求wi的方法,从左往右求wi,每次把新产生效果翻转区间ak~bk取反 同时把新失去效果的翻转区间的ak~bk取反。。统计1总数。。。
代码:
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<vector> 8 #include<map> 9 #include<queue> 10 #include<cctype> 11 #include<cmath> 12 13 #define eps 1e-9 14 #define N 201010 15 #define sqr(x) ((x)*(x)) 16 #define Rep(i,n) for(int i = 0; i<n; i++) 17 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 18 #define X first 19 #define Y second 20 #define mp(x,y) make_pair(x,y) 21 22 using namespace std; 23 typedef long long LL; 24 typedef pair<int,int> pii; 25 26 int que[N],mark[N]; 27 int main(){ 28 int n = 0, cas,kind , a , x; 29 double sum = 0; 30 scanf("%d", &cas ); 31 int g = 0 , h = 0; 32 que[h++] = 0; 33 while ( cas -- ){ 34 scanf("%d", &kind ); 35 if ( kind == 1 ) { 36 scanf("%d%d",&a, &x ); 37 sum += x*1.0*a; 38 mark[g+a-1] += x; 39 } 40 else if ( kind == 2 ){ 41 scanf("%d", &x ); 42 mark[h] = 0; 43 que[h++] = x; 44 sum += x; 45 } 46 else { 47 mark[h-2] += mark[h-1]; 48 sum -= que[h-1]+mark[h-1]; 49 h--; 50 } 51 printf("%.10f\n", sum/(h-g) ); 52 } 53 54 return 0; 55 }
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<vector> 8 #include<map> 9 #include<queue> 10 #include<cctype> 11 #include<cmath> 12 13 #define eps 1e-9 14 #define N 200010 15 #define sqr(x) ((x)*(x)) 16 #define Rep(i,n) for(int i = 0; i<n; i++) 17 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 18 #define X first 19 #define Y second 20 #define mp(x,y) make_pair(x,y) 21 22 using namespace std; 23 typedef long long LL; 24 typedef pair<int,int> pii; 25 26 int mark[N][2],a[N],n; 27 LL dp[N][2]; 28 bool g[N][2]; 29 30 void solve(int i,int k){ 31 mark[i][k] = 1; 32 dp[i][k] = a[i]; 33 int j = i; 34 if ( k ) j+=a[i]; else j-=a[i]; 35 36 if ( j >=1 && j <= n ){ 37 if ( j == 1 && (k^1) == 0 ) g[i][k] = 1; 38 else if ( mark[j][k^1] == 1 ) dp[i][k] = -1; 39 else { 40 if ( mark[j][k^1] == 0 ) solve(j,k^1); 41 if ( dp[j][k^1] == -1 ) dp[i][k] = -1; 42 else { 43 dp[i][k] += dp[j][k^1]; 44 g[i][k] = g[j][k^1]; 45 } 46 } 47 } 48 else g[i][k] = 0; 49 50 mark[i][k] = 2; 51 } 52 53 int main(){ 54 scanf("%d", &n ); 55 for(int i = 2; i<=n; i++) scanf("%d", &a[i] ); 56 mark[1][1] = 1; 57 for(int i = 2; i<=n; i++) 58 if ( mark[i][0]==0 ) { 59 solve(i,0); 60 } 61 for(int i = 1; i<=n-1; i++) { 62 if ( dp[i+1][0] == -1 ) printf("-1\n"); 63 else printf("%I64d\n" , dp[i+1][0]+i+(g[i+1][0]?i:0) ); 64 } 65 return 0; 66 }
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<vector> 8 #include<map> 9 #include<queue> 10 #include<cctype> 11 #include<cmath> 12 13 #define eps 1e-9 14 #define sqr(x) ((x)*(x)) 15 #define Rep(i,n) for(int i = 0; i<n; i++) 16 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 17 #define X first 18 #define Y second 19 #define mp(x,y) make_pair(x,y) 20 21 using namespace std; 22 typedef long long LL; 23 typedef pair<int,int> pii; 24 25 #define N 305 26 #define M 100010 27 #define MOD 1000000007 28 int n,q,tol; 29 int to[N]; 30 int mark[N],a[N]; 31 int dp[2][M]; 32 bool st[N]; 33 34 bool dfs(int x){ 35 mark[x] = 2; 36 if ( to[x] == 0 ) return true; 37 if ( mark[to[x]] == 2 ) return false; 38 else if ( !dfs(to[x]) ) return false; 39 a[x] += a[to[x]]; 40 return true; 41 } 42 43 int solve(){ 44 for(int i = 1; i<=n; i++) 45 if ( mark[i]==0 ) { 46 st[i] = true; 47 if ( !dfs(i) ) return 0; 48 } 49 for(int i = 1; i<=n; i++){ 50 if ( mark[i] == 1 ) return 0; 51 if ( !st[i] ) tol -= a[i]; 52 if ( tol < 0 ) return 0; 53 } 54 memset( dp , 0 , sizeof(dp) ); 55 dp[0][0] = 1; 56 for(int i = 0; i<n; i++){ 57 int g = i%2 , h = (i+1)%2; 58 memset( dp[h] , 0 , sizeof(dp[h]) ); 59 for(int j = 0; j<=tol; j++){ 60 dp[h][j] += dp[g][j]; 61 dp[h][j] %= MOD; 62 if ( j+a[i+1] <= tol ){ 63 dp[h][j+a[i+1]] += dp[h][j]; 64 dp[h][j+a[i+1]] %= MOD; 65 } 66 } 67 } 68 return dp[n%2][tol]; 69 } 70 int main(){ 71 scanf("%d%d%d", &n, &q, &tol ); 72 Rep(i,n) scanf("%d", &a[i+1] ); 73 while ( q -- ) { 74 int x,y; 75 scanf("%d%d", &x, &y ); 76 to[y] = x; 77 mark[x] = 1; 78 } 79 printf("%d\n" , solve() ); 80 return 0; 81 }
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<vector> 8 #include<map> 9 #include<queue> 10 #include<cctype> 11 #include<cmath> 12 13 #define eps 1e-9 14 #define N 10010 15 #define sqr(x) ((x)*(x)) 16 #define Rep(i,n) for(int i = 0; i<n; i++) 17 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 18 #define X first 19 #define Y second 20 #define mp(x,y) make_pair(x,y) 21 22 using namespace std; 23 typedef long long LL; 24 typedef pair<int,int> pii; 25 26 int n; 27 LL a[N]; 28 int dp[N],b[N]; 29 int main(){ 30 scanf("%d", &n ); 31 Rep(i,n) { 32 cin>>a[i]; 33 while ( a[i]%2 == 0 ){ 34 b[i]++; 35 a[i]/=2; 36 } 37 } 38 dp[0] = 1; 39 int ans = n; 40 Rep(i,n){ 41 dp[i] = i; 42 Rep(j,i) 43 if ( a[j]%a[i] == 0 && (b[j]+i-j>=b[i] || b[i]<=i-j-1) ) 44 dp[i] = min( dp[j]+i-j-1 , dp[i] ); 45 ans = min( ans , n-i-1+dp[i] ); 46 } 47 printf("%d\n" , ans ); 48 return 0; 49 }
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<vector> 8 #include<map> 9 #include<queue> 10 #include<cctype> 11 #include<cmath> 12 13 #define eps 1e-9 14 #define N 100010 15 #define sqr(x) ((x)*(x)) 16 #define Rep(i,n) for(int i = 0; i<n; i++) 17 #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) 18 #define X first 19 #define Y second 20 #define mp(x,y) make_pair(x,y) 21 22 using namespace std; 23 typedef long long LL; 24 typedef pair<int,int> pii; 25 26 int n,m,data[N]; 27 pii que[N*2]; 28 29 struct Segtree{ 30 int left[N*4],right[N*4]; 31 int key[N*4][2],mark[N*4]; 32 void down(int step){ 33 if ( !mark[step] ) return; 34 mark[step] = 0; 35 Rep(k,2) 36 mark[step*2+k]^= 1, 37 swap( key[step*2+k][0] , key[step*2+k][1] ); 38 } 39 void build(int l,int r,int step){ 40 left[step] = l , right[step] = r; 41 key[step][0] = 0 , key[step][1] = r-l+1; 42 mark[step] = 0; 43 if ( l == r ) return; 44 int mid=(l+r)/2; 45 build(l,mid,step*2); 46 build(mid+1,r,step*2+1); 47 } 48 void updata(int l,int r,int step){ 49 if ( left[step] == l && right[step] == r ){ 50 mark[step] ^= 1; 51 swap( key[step][0] , key[step][1] ); 52 return; 53 } 54 down(step); 55 int mid=(left[step]+right[step])/2; 56 if ( r<=mid ) updata(l,r,step*2); 57 else if ( mid<l ) updata(l,r,step*2+1); 58 else{ 59 updata(l,mid,step*2); 60 updata(mid+1,r,step*2+1); 61 } 62 Rep(k,2) key[step][k] = key[step*2][k]+key[step*2+1][k]; 63 } 64 int ask(int l,int r,int k,int step){ 65 if ( left[step] == l && right[step] == r ) return key[step][k]; 66 down(step); 67 int mid=(left[step]+right[step])/2; 68 if ( r <= mid ) return ask(l,r,k,step*2); 69 else if ( mid < l ) return ask(l,r,k,step*2+1); 70 else return ask(l,mid,k,step*2)+ask(mid+1,r,k,step*2+1); 71 } 72 }tree; 73 74 int main(){ 75 scanf("%d%d", &n, &m ); 76 Rep(i,n) scanf("%d", &data[i] ); 77 sort( data , data+n ); 78 Rep(i,m) { 79 int x,y; 80 scanf("%d%d", &x, &y ); 81 que[i*2] = mp(x,y); 82 que[i*2+1] = mp(y+1,-x); 83 } 84 sort( que , que+m*2 ); 85 tree.build(0,n,1); 86 int j = 0; 87 LL ans = 0; 88 Rep(i,n){ 89 while ( j<2*m && data[i] >= que[j].X ){ 90 int l,r; 91 if ( que[j].Y > 0 ) l = i , r = upper_bound(data,data+n,que[j].Y)-data-1; 92 else r = i-1 , l = lower_bound(data,data+n,-que[j].Y)-data; 93 if ( l<=r ) tree.updata(l,r,1); 94 j++; 95 } 96 int tol = (i?tree.ask(0,i-1,0,1):0)+(i<n-1?tree.ask(i+1,n-1,0,1):0); 97 ans += ((LL)tol)*(tol-1)/2; 98 tree.updata(i,i,1); 99 } 100 ans = ((LL)n)*(n-1)*(n-2)/6-ans; 101 cout<<ans<<endl; 102 return 0; 103 }