JNday1-pm
T1可以是一个贪心用到一个STL
//multiset 之前还真没用过,还可以线段树来维护
T2 手算,gg算错,然而这道题写出暴力后打表是可以A掉的
T3骗分,分类k,复杂度是n^k,然而时间只让我写到k=5,数组开小挂掉应过的一个点,正解没听懂
总结:骗分很重要,暴力骗分要练好,这套题只会骗分了。。。。
水题(water)
//竟然只有 #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> using namespace std; const int N = 1e3 + 10; struct Node{ int x, y; }e1[N], e2[N]; int n; int head[N], now = 1; bool vis[N]; int answer, ans; struct Node1{ int u, v, nxt; }E[N * N]; inline void add(int u, int v) { E[now].v = v; E[now].nxt = head[u]; head[u] = now ++; } inline int read() { int x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x; } void dfs(int js) { if(js == n + 1) { answer = max(answer, ans); return ; } if(head[js] == -1) dfs(js + 1); else for(int i = head[js]; ~ i; i = E[i].nxt) { int v = E[i].v; if(!vis[v]) { vis[v] = 1; ans ++; dfs(js + 1); vis[v] = 0; ans --; } } } int main() { freopen("water.in", "r", stdin); freopen("water.out", "w", stdout); n = read(); for(int i = 1; i <= n; i ++) head[i] = -1; for(int i = 1; i <= n; i ++) e1[i].x = read(), e1[i].y = read(); for(int i = 1; i <= n; i ++) e2[i].x = read(), e2[i].y = read(); for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) if(e1[i].x >= e2[j].x && e1[i].y >= e2[j].y) add(i, j); dfs(1); printf("%d", answer); return 0; } /* 3 2 3 5 7 6 8 4 1 2 5 3 4 */
//std #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <set> using namespace std; int n; multiset <int> s; struct node {int x,y;} a[100005],b[100005]; int cmp(node i,node j) {return i.x<j.x;} int main() { freopen("water.in","r",stdin); freopen("water.out","w",stdout); int T; T=1; while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y); for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y); sort(a,a+n,cmp); sort(b,b+n,cmp); s.clear(); int k=0,ans=0; for(int i=0;i<n;i++) { while(a[i].x>=b[k].x&&k<n) { s.insert(b[k].y); k++; } if(s.empty())continue; multiset<int>::iterator it=s.upper_bound(a[i].y); if (it==s.begin()) continue; it--; ans++; s.erase(it); } printf("%d\n",ans); } return 0; }
梦境(dream)
#include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; int n,sum,ans,dp[1005][1005],DP[1005][1005],i,j,k,l; int main() { freopen("dream.in","r",stdin); freopen("dream.out","w",stdout); scanf("%d",&n); sum=int(log(n)/log(2)+0.000000001)+1; dp[1][1]=1; for (i=1; i<sum; i++) { for (j=1; j<=n; j++) for (k=1; k<=n; k++) if (dp[j][k]) for (l=k+1; l<=j+1; l++) DP[min(n,j+l)][l]+=dp[j][k]; for (j=1; j<=n; j++) for (k=1; k<=n; k++) {dp[j][k]=DP[j][k];DP[j][k]=0;} } for (j=1; j<=n; j++) ans+=dp[n][j]; cout<<sum<<' '<<ans; return 0; }
动态规划(dp)
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> using namespace std; const int N = 200; int jc[N]; int c[N]; int n, k, answer = 99999999; int a[N], f[N][N]; inline int read() { int x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x; } int main() { freopen("dp.in", "r", stdin); freopen("dp.out", "w", stdout); n = read(); k = read(); jc[1] = 1; for(int i = 2; i <= 10; i ++)jc[i] = jc[i - 1] * i; c[0] = c[1] = 0; c[2] = 1; for(int i = 3; i <= 10; i ++) c[i] = jc[i] / jc[i - 2] / 2; for(int i = 1; i <= n; i ++) a[i] = read(); f[1][a[1]] ++; for(int i = 2; i <= n; i ++) { for(int j = 0; j <= n; j ++) f[i][j] = f[i - 1][j]; f[i][a[i]] ++; } if(k == 1) { int aa = 0; for(int i = 0; i <= n; i ++) aa += c[f[n][i]]; printf("%d", aa); return 0; } if(k == 2) { for(int i = 1; i < n; i ++)//中间分割 { int js = 0; for(int j = 0; j <= n; j ++) js += c[f[i][j]] + c[f[n][j] - f[i][j]]; answer = min(answer, js); } printf("%d", answer); return 0; } if(k == 3) { for(int i = 1; i < n - 1; i ++) for(int j = i + 1; j < n; j ++) { int js = 0; for(int k = 0; k <= n; k ++) js += c[f[i][k]] + c[f[j][k] - f[i][k]] + c[f[n][k] - f[j][k]]; answer = min (answer, js); } printf("%d", answer); return 0; } if(k == 4) { for(int i = 1; i < n - 2; i ++) for(int j = i + 1; j < n - 1; j ++) for(int k = j + 1; k < n; k ++) { int js = 0; for(int kk = 0; kk <= n; kk ++) { js += c[f[i][kk]] + c[f[j][kk] - f[i][kk]] + c[f[k][kk] - f[j][kk]] + c[f[n][kk] - f[k][kk]]; } answer = min(answer, js); } printf("%d", answer); return 0; } if(k == 5) { for(int i = 1; i < n - 3; i ++) for(int j = i + 1; j < n - 2; j ++) for(int l = j + 1; l < n - 1; l ++) for(int r = l + 1; r < n; r ++) { int js = 0; for(int k = 0; k <= n; k ++) { js += c[f[i][k]] + c[f[j][k] - f[i][k]] + c[f[l][k] - f[j][k]] + c[f[r][k] - f[l][k]] + c[f[n][k] - f[r][k]]; } answer = min (answer, js); } printf("%d", answer); return 0; } printf("186"); return 0; }
//std #include<iostream> #include<cstdio> using namespace std; const int N=100010; typedef long long LL; int c[N],a[N]; LL f[N],g[N]; int p,q,n,k; LL tot; void move(int l,int r) // [p,q]之前的区间 { while (l<p) p--,tot+=c[a[p]],c[a[p]]++; while (r>q) q++,tot+=c[a[q]],c[a[q]]++; while (p<l) c[a[p]]--,tot-=c[a[p]],p++; while (r<q) c[a[q]]--,tot-=c[a[q]],q--; } void work(int l,int r,int fl,int fr) //需要求dp[fl] ~ dp[fr] 最优解一定从l~r中的某一个转移过来 { if (fl>fr) return; int mid=(fl+fr)>>1,mi; LL mx=1LL<<60; for (int i=l;i<=r;i++) if (i<mid) { move(i+1,mid); -> tot=sum(i+1,mid); if (f[i]+tot<mx) mx=f[i]+tot,mi=i; } g[mid]=mx; work(l,mi,fl,mid-1); work(mi,r,mid+1,fr); } int main() { freopen("dp.in","r",stdin); freopen("dp.out","w",stdout); scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",&a[i]); f[0]=0; for (int i=1;i<=n;i++) f[i]=1LL<<60; while (k--) { p=1,q=0,tot=0; for (int i=1;i<=n;i++) c[i]=0; work(0,n-1,1,n); for (int i=0;i<=n;i++) f[i]=g[i],g[i]=0; } cout<<f[n]; return 0; }