2015暑期多校训练第一场 1,2,3
2015-09-03 21:20
267 查看
// 2015暑期多校训练第一场 1,2,3 // // 本来想一天能够复习一套的,结果实在太艰难,一题差不多都能搞一天呢 // 而且内心的激动也是想在此时分享分享,前两道大神说的水题,我都理解 // 了大半天,第三题更是理解了三四天才懂了那么一丁点.继续加油吧,明天 // 继续搞! // hdu 5288 OO’s Sequence // // 对于一个a[i]记录左边一个L右边一个R,分别 // 代表最接近a[i]并且能够被a[i]整除的位置 // 每个a[i]的贡献值是(R[i] - i) * (i - L[i]) // 用一个pre值,记录每个数出现的位置. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int maxn = 100008; const ll MOD = 1e9 + 7; int a[maxn]; int L[maxn]; int R[maxn]; int n; vector<int> p[10008]; int pre[maxn]; void init(){ for (int i=1;i<=10000;i++){ p[i].clear(); for (int j=1;j*j<=i;j++){ if (i%j==0){ p[i].push_back(j); if (j*j!=i) p[i].push_back(i/j); } } } } void input(){ for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } } void solve(){ memset(pre,0,sizeof(pre)); for (int i=1;i<=n;i++){ int u = a[i]; int ind = 0; for (int j=0;j<p[u].size();j++){ ind = max(ind,pre[p[u][j]]); } L[i] = ind; pre[u] = i; } memset(pre,0x7f,sizeof(pre)); for (int i=n;i>=1;i--){ int u = a[i]; int ind = n + 1; for (int j=0;j<p[u].size();j++){ ind = min(ind,pre[p[u][j]]); } R[i] = ind; pre[u] = i; } ll ans = 0; for (int i=1;i<=n;i++){ ans = (ans + (ll)(i-L[i]) * (R[i] - i))%MOD; } printf("%I64d\n",ans); } int main(){ init(); freopen("1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ input(); solve(); } } // hdu 5289 Assignment 单调队列 // // 题目大意: // // 题目的意思就是让你求满足最大值最小值之差小与k的区间个数 // // 解题思路: // // 单调队列,众所周知,单调队列能够维护滑动窗口的最大值和最小值 // 的问题.这里两者都有,我们都维护即可.我们用两个指针.一个指针表示 // 当前插入的元素,另一个指针表示满足条件的开始的元素的位置.维护单 // 调队列的时候我们插入一个元素,当发现插入该元素时,不满足题目所要 // 求的条件,并且第一个指针指向的位置出队.这时两个指针之间的距离就 // 是我们所能得到的区间的数目,累加结果就好.最后还要记得当所有的元 // 素都入队时,此时要看看j是否是最后的位置,因为此时还有满足条件的 // 区间. // // 感悟: // // 这道题多校训练的时候,是MY做出来的,用的就是单调队列,当时并不 // 怎么明白,后来也自己做了一遍,能想到维护最大值和最小值,但是这之间 // 的距离就不太清楚了.看了看题解,发现确实很奇妙.然后自己仔细仔细的 // 体会了一番,确实很不错.感谢这位神牛.也有的大神用的线段树做出来的 // 也有的是RMQ+二分.有多种解法.多开阔开阔思路,总是好的.继续加油哟~~~ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1e5 + 8; int n,k; int a[maxn]; int deqmax[maxn]; int deqmin[maxn]; void input(){ scanf("%d%d",&n,&k); for (int i = 1; i <= n; i++){ scanf("%d",&a[i]); } } void solve(){ int headmax,tailmax,headmin,tailmin; headmax = tailmax = headmin = tailmin = 0; long long ans = 0; int j = 1; for (int i=1;i <= n; i++){ while(headmax < tailmax && a[deqmax[tailmax-1]] <= a[i]) tailmax--; deqmax[tailmax++] = i; while(headmin < tailmin && a[deqmin[tailmin-1]] >= a[i]) tailmin--; deqmin[tailmin++] = i; while(headmin < tailmin && headmax < tailmax && a[deqmax[headmax]]-a[deqmin[headmin]] >= k){ ans += i - j; if (j == deqmax[headmax]) headmax++; if (j == deqmin[headmin]) headmin++; j++; } } while(j <= n){ ans += n + 1 - j; j++; } printf("%I64d\n",ans); } int main(){ int t; //freopen("1.txt","r",stdin); scanf("%d",&t); while(t--){ input(); solve(); } } // hdu 5290 Bombing plan // // 题目大意: // // 给你一颗树,树上每个节点有一个权值w,当炸毁一个节点 // 时,距离它为w以内的点都被炸毁.则问当所有点被炸毁时 // 最小需要炸毁几个点. // // 解题思路: // // 树形dp.我们设立两个数组F[I][J],G[I][J].前者表示 // I及I子树中所有节点全被炸毁,并且沿父节点向上距离 // 为J的点也被炸毁.后者表示I及I的子树中部分节点被炸毁 // 并且未被炸毁的点离I最远为J. // 转移方程为: // 不取i点 // F[i][j] = F[v][j+1] + min(F[L][0...j+1],G[L][0...j-1]); // G[i][j] = g[v][j-1] + min(F[L][0....j],G[L][0...j-1]); // G[i][0] = sigma(f[v][0]); // // 取i点 // F[i][w[i]] = 1 + min(F[L][0...w[u]+1],G[L][0...w[u]-1]); // // 如果不好理解的话,那么本人按照自己的理解说一下,首先是F[i][j]. // 先选一个满足条件的能达到i向上距离为j的则为F[v][j+1].此时其他 // 的节点,子节点子树全被炸毁的范围F[L][0...j+1],子节点子树未被 // 全部炸毁g[i][j-1].G[i][j]同样是首先选择一个离i未炸毁的G[v][j-1] // 其他的还是两种选择,要么未炸毁距离小于等于j要么全被炸毁. // // 初始化的时候单个叶子节点g[i][0] = 0,f[i][w[i]] = 1;其他的无穷大 // 但是不宜太大,容易造成数据溢出 // // 看到一位大神写的在这题中,将无根树转化为有根树的时候,将1作为根. // 并将1本身的节点另起一个编号挂在1上.这样的做法我感觉十分奇妙.自己还是 // 不很理解.希望大牛们能够不吝惜的指点小子一二.小子不慎感激 // // 感悟: // // 多校第一场的第三题,当时根本就不会做,题解也看不懂.现在经过了玩耍的开心 // 时间,是时候逼迫自己去理解了,要不然水平怎么能提高呢,继续加油吧 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <vector> #define cls(x,a) memset(x,(a),sizeof(x)) #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int maxn = 1e5 + 8; const int inf = 0x01010101; vector<int> e[maxn]; int a[maxn]; int F[maxn][111]; int G[maxn][111]; int p[maxn][111]; int q[maxn][111]; int n; void input(){ for (int i=1;i<=n;i++){ e[i].clear(); } for (int i = 1;i <= n;i++){ scanf("%d",&a[i]); } e[1].push_back(n+1); for (int i=1;i < n;i++){ int u,v; scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } cls(F,inf); cls(G,inf); cls(p,inf); cls(q,inf); } void dfs(int u,int fa){ for (int i=0;i<e[u].size();i++){ int v = e[u][i]; if (v == fa) continue; dfs(v,u); } if (e[u].size()==1){ G[u][0] = 0; F[u][a[u]] = 1; return; } for (int i=0;i<e[u].size();i++){ int v = e[u][i]; if (v == fa) continue; p[v][0] = F[v][0]; q[v][0] = G[v][0]; for (int j=1;j<103;j++){ p[v][j] = min(p[v][j-1],F[v][j]); q[v][j] = min(q[v][j-1],G[v][j]); } } for (int j=0;j<103;j++){ for (int k=0;k<e[u].size();k++){ int v = e[u][k]; if (v == fa) continue; if (F[v][j+1] == inf) continue; int f = F[v][j+1]; for (int i=0;i<e[u].size();i++){ int t = e[u][i]; if (i==k || t == fa) continue; if (j) f += min(p[t][j+1],q[t][j-1]); else f += p[t][j+1]; } F[u][j] = min(F[u][j],f); } } int g = 0; for (int i=0;i<e[u].size();i++){ int v = e[u][i]; if (v==fa) continue; g += F[v][0]; } G[u][0] = min(G[u][0],g); for (int j=1;j<103;j++){ for (int k=0;k<e[u].size();k++){ int v = e[u][k]; if (v == fa) continue; if (G[v][j-1] == inf) continue; g = G[v][j-1]; for (int i=0;i<e[u].size();i++){ int t = e[u][i]; if (i==k || t == fa) continue; g += min(p[t][j],q[t][j-1]); } G[u][j] = min(G[u][j],g); } } int f = 1; for (int i=0;i<e[u].size();i++){ int v = e[u][i]; if (v == fa) continue; if (a[u]){ f += min(p[v][a[u]+1],q[v][a[u]-1]); }else { f += p[v][a[u]+1]; } } F[u][a[u]] = min(F[u][a[u]],f); } void solve(){ dfs(1,0); int ans = inf; for (int j=0;j<103;j++){ ans = min(ans,F[1][j]); } printf("%d\n",ans); } int main(){ freopen("1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ input(); solve(); } }
相关文章推荐
- php大力力 [045节] 兄弟连高洛峰 PHP教程 2014年[已发布,点击下载]
- hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)
- HTTP 状态码的完整列表
- 关于结构体的操作符重载和定义在内部的函数
- 继承中的构造方法
- Python
- 函数指针数组
- AJAX学习笔记
- newssoj1004逐个击破attack(排序+并查集)
- jQuery基础学习4——jQuery容错性
- 背包问题
- 蓝懿-打飞机图片,内存管理基础 刘国斌老师
- poj 2155 Matrix(二维树状数组)
- C++模板类编写需要注意的一点
- [转]在Ubuntu中安装Python科学计算环境
- [转载]Qt之中文显示(QMessageBox、QLineEdit右键菜单等)
- 蓝汛ChinaCache助力大阅兵全球直播
- 运用Polygon类绘制六边形
- UVALive 7043 International Collegiate Routing Contest 字典树
- 详解SVN提交更新七大准则