Codeforces 960 二进制构造子序列 完全二叉树shift模拟 主席树/MAP DP
A
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 0x3f3f3f3f
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[][] = {{, }, { , }, { , -}, { -, }};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
int main()
{
string f;
cin >> f;
int len = f.size();
int flag = ;
int numa = ;
int numb = ;
int numc = ;
int now = ;
for (int i = ; i < len; i++)
{
if (f[i] - 'a' < now)
{
flag = ;
break;
}
else
{
now = max(now, f[i] - 'a');
}
}
if (!flag)
{
cout << "NO" << endl;
return ;
}
for (int i = ; i < len; i++)
{
if (f[i] == 'a')
{
numa++;
}
else if (f[i] == 'b')
{
numb++;
}
else
{
numc++;
}
}
if (numa < || numb < )
{
cout << "NO" << endl;
return ;
}
if (numc == numa || numc == numb)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
B
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 0x3f3f3f3f
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[][] = {{, }, { , }, { , -}, { -, }};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
priority_queue<ll, vector<ll>, less<ll>> que;
ll a[];
ll b[];
int main()
{
ll anser = ;
ll n, k1, k2;
cin >> n >> k1 >> k2;
for (int i = ; i <= n; i++)
{
scanf("%lld", &a[i]);
}
for (int i = ; i <= n; i++)
{
scanf("%lld", &b[i]);
que.push(abs(a[i] - b[i]));
anser += abs(a[i] - b[i]) * abs(a[i] - b[i]);
}
int cur = k1 + k2;
while (cur)
{
ll now = que.top();
que.pop();
if (now == )
{
cur--;
que.push();
anser += ;
}
else
{
cur--;
que.push(now - );
anser -= 1LL * now * now;
anser += 1LL * (now - ) * (now - );
}
}
cout << anser << endl;
}
C
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 0x3f3f3f3f
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[][] = {{, }, { , }, { , -}, { -, }};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
priority_queue<ll, vector<ll>, less<ll>> que;
vector<ll> ans;
int main()
{
//freopen("out.txt","w",stdout);
ll x, d;
cin >> x >> d;
// if(x<=10000)
// {
// for(ll i=1;x;i+=d+1)
// {
// cout<<i<<" ";
// x--;
// }
// return 0;
// }
ll cur = ;
if (x == )
{
cout << << endl;
cout << << endl;
return ;
}
if (x & )
{
ans.push_back(1e17 - );
x -= ;
}
for (ll i = ; i <= ; i++)
{
if ((1LL << i)&x)
{
que.push(i);
}
}
while (!que.empty())
{
ll number = que.top();
que.pop();
for (ll i = ; i <= number; i++)
{
ans.push_back(cur);
}
cur += d;
ans.push_back(cur);
cur += d;
}
cout << ans.size() << endl;
for (ll ch : ans)
{
cout << ch << " ";
}
}
D
给你一个完全二叉树有三种操作
1.把值为X的节点所在当前层 移动K次
2.把值为X的节点所在当前层 移动K次 子树也跟着移动
3.询问你值为X所在结点到根节点路径上节点的值
shift[i]表示第i层移动的次数
第二个操作很好处理 第三个操作就是在第二个操作上pushdown 下一层移动的次数是上一层的两倍
(记得取模操作)
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 0x3f3f3f3f
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[][] = {{, }, { , }, { , -}, { -, }};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
int Q;
int T;
ll level;
ll X, K;
ll lenth, position;
ll shift[];
void update(ll x, ll K)
{
shift[x] += K;
shift[x] %= (1LL << (x - ));
}
void pushdown(ll x, ll K)
{
shift[x] += K;
shift[x] %= (1LL << (x - ));
if (x + < )
{
K = (K << );
pushdown(x + , K);
}
}
ll getpos(ll level, ll x)
{
ll l = 1LL << (level - );
ll r = (1LL << level) - ;
ll now = x + shift[level];
if (l <= now && now <= r)
{
return now;
}
if (now < l)
{
ll cha = l - now - ;
return r - cha;
}
else
{
ll cha = now - r - ;
return l + cha;
}
}
void print(ll level, ll pos)
{
if (level == )
{
cout << ;
return ;
}
ll now = pos - shift[level];
ll l = 1LL << (level - );
ll r = (1LL << level) - ;
if (l <= now && now <= r)
{
cout << now << " ";
print(level - , pos / );
return;
}
if (now < l)
{
ll cha = l - now - ;
cout << r - cha << " ";
}
else
{
ll cha = now - r - ;
cout << l + cha << " ";
}
print(level - , pos / );
return ;
}
int main()
{
//freopen("out.txt","w",stdout);
cin >> Q;
while (Q--)
{
int T;
scanf("%d %lld", &T, &X);
for (ll i = ; i >= ; i--)
{
if ((1LL << (i - ))&X)
{
if (((1LL << i)&X) == )
{
level = i;
break;
} }
}
//cout<<level<<" ";
if (T == )
{
scanf("%lld", &K);
if (X == )
{
continue;
}
K %= 1LL << (level - );
update(level, K);
}
else if (T == )
{
scanf("%lld", &K);
if (X == )
{
continue;
}
K %= 1LL << (level - );
pushdown(level, K);
}
else
{
if (X == )
{
cout << << endl;
continue;
}
cout << X << " ";
position = getpos(level, X);
//cout << position;
print(level - , position / );
cout << endl;
}
}
}
E
F
先来做F的简化版
http://codeforces.com/contest/459/problem/E
求有向图的最长严格递增路径
dp[i]表示以第i条边为结尾的最长路径 g[i]表示以i结点为结尾的最长路径
所以dp[i]=dp[edge[i].from]+1即以第i条边结尾的答案是以该边from结尾的最长路径长度+其本身
首先排序 相同大小的边之间是不会相连的
而如果每遍历一条边就g[edge[i].to]=max(g[edge[i].to],dp[i])的话 如果edge[i+1].from=edge[i].to 就变成这两条边相连了所以相同值的边要分处理
复杂度NLOGN
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 300007
using namespace std;
int n, m;
int dp[MAX], g[MAX];
struct Edge
{
int u, v, w;
bool operator < ( const Edge& a ) const
{
return w < a.w;
}
} e[MAX];
int main ( )
{
while ( ~scanf ( "%d%d" , &n , &m ) )
{
for ( int i = ; i < m ; i++ )
{
scanf ( "%d%d%d" , &e[i].u , &e[i].v , &e[i].w );
}
sort ( e , e + m );// 排序
int t = ;
e[m].w = -;//使得最后一组边也能更新
int ans = ; //答案
for ( int i = ; i < m ; i++ ) //从小到大枚举
{
int v = e[i].v;
int u = e[i].u;
int w = e[i].w;
dp[i] = g[e[i].u] + ; //以第i条边结尾的答案是以e[i].from节点为结尾的最长路径+它本身
if ( e[i].w != e[i + ].w )
{
for ( int j = t ; j <= i ; j++ ) //处理相同边
{
g[e[j].v] = max ( g[e[j].v] , dp[j] );//更新e[i].to的答案 以便处理下一组边
}
t = i + ;//重置相同边的起点
}
ans = max ( ans , dp[i] );
}
printf ( "%d\n" , ans );
}
}
现在来做F
如果用上面的方法来做 不能保证下标不能有逆序对这个条件
如果去掉edge[i].from=edge[j].to这个条件的话 这道题就变成一道裸的LIS
如果用来DP的话 普通的dp[i][j]数组表示以i为结尾的权重最大为j的最长递增路径长度 因为i和j都是1e5的会炸
但是用MAP来存的话 因为每个dp[i]表示的都是一个树状数组 每次插入和询问都是LOGN的 所以最多只会涉及到NLOGN个节点 可以接受
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 0x3f3f3f3f
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[][] = {{, }, { , }, { , -}, { -, }};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
const int N = 1e5 + ;
map<int, int> bits[N];
int query(int u, int x)
{
int ans = ;
while (x)
{
ans = max(ans, bits[u][x]);
x -= x & -x;
}
return ans;
}
void update(int u, int x, int v)
{
while (x < N)
{
bits[u][x] = max(bits[u][x], v);
x += x & -x;
}
}
int main()
{
int n, m, u, v, w;
int anser = ;
int cur;
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++)
{
scanf("%d%d%d", &u, &v, &w);
w++;
cur = query(u, w - ) + ;
update(v, w, cur);
anser = max(anser, cur);
}
printf("%d\n", anser);
return ;
}
用主席树来做的话 其实和MAP DP递推是同理的 只建立需要的节点 其他节点忽略
#include<cstdio>
#include<algorithm>
#define lowbit(x) (x&-x)
using namespace std;
const int maxn=;
int n,m,f[maxn],rt[maxn],sz;
struct tree{int l,r,mx;}t[maxn*];
void insert(int& k,int l,int r,int x,int y){
if(!k)k=++sz;t[k].mx=max(t[k].mx,y);
if(l==r)return;
int mid=(l+r)>>;
if(x<=mid)insert(t[k].l,l,mid,x,y);
else insert(t[k].r,mid+,r,x,y);
}
int query(int k,int l,int r,int x){
if(l==r)return t[k].mx;
int mid=(l+r)>>;
if(x<=mid)return query(t[k].l,l,mid,x);
else return max(t[t[k].l].mx,query(t[k].r,mid+,r,x));
}
int main(){
scanf("%d%d",&n,&m);
int ans=;
for(int i=;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
f[i]=query(rt[u],,,w-)+;
insert(rt[v],,,w,f[i]);
ans=max(ans,f[i]);
}
printf("%d",ans);
return ; }
Codeforces 960 二进制构造子序列 完全二叉树shift模拟 主席树/MAP DP的更多相关文章
- CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度
题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...
- CodeForces 294B Shaass and Bookshelf 【规律 & 模拟】或【Dp】
这道题目的意思就是排两排书,下面这排只能竖着放,上面这排可以平着放,使得宽度最小 根据题意可以得出一个结论,放上这排书的Width 肯定会遵照从小到大的顺序放上去的 Because the total ...
- Codeforces 622C Not Equal on a Segment 【线段树 Or DP】
题目链接: http://codeforces.com/problemset/problem/622/C 题意: 给定序列,若干查询,每个查询给定区间和t,输出区间内任意一个不等于t的元素的位置. 分 ...
- Codeforces Round #426 (Div. 2) D. The Bakery 线段树优化DP
D. The Bakery Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought req ...
- 4.13 省选模拟赛 树 树形dp 卷积 NTT优化dp.
考试的时候 看到概率 看到期望我就怂 推了一波矩阵树推自闭了 发现 边权点权的什么也不是. 想到了树形dp 维护所有边的断开情况 然后发现数联通块的和再k次方过于困难. 这个时候 应该仔细观察一下 和 ...
- bzoj2989&&4170数列——二进制分组+主席树
题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...
- codeforces 1041 e 构造
Codeforces 1041 E 构造题. 给出一种操作,对于一棵树,去掉它的一条边.那么这颗树被分成两个部分,两个部分的分别的最大值就是这次操作的答案. 现在给出一棵树所有操作的结果,问能不能构造 ...
- Tree Constructing CodeForces - 1003E(构造)
题意: 就是让构造一个直径为d的树 每个结点的度数不能超过k 解析: 先构造出一条直径为d的树枝 然后去遍历这条树枝上的每个点 为每个点在不超过度数和直径的条件下添加子嗣即可 #include & ...
- Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)
题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...
随机推荐
- Oracle诊断:drop table失败[转]
转: From <http://blog.csdn.net/cyxlxp8411/article/details/7775113> 今天在drop一张表的时候报ORA-00054错误 SQ ...
- 移动Anaconda安装目录后导致图标变白以及Anaconda Navigator,Anaconda Prompt,jupyter notebook和spyder启动不了的解决方法
Q:因为移动了Anaconda3的安装目录,所以Anaconda3的相应应用程序启动不了,包括图标也会变白 解决方法:修改对应快捷键的属性,有对应的启动位置,修改下位置路径配置以及图标(Anacond ...
- Git-Runoob:Git 教程
ylbtech-Git-Runoob:Git 教程 1.返回顶部 1. Git 教程 Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torva ...
- OpenStack Rally 质量评估与自动化测试利器
目录 文章目录 目录 问题描述 Rally 简介 应用场景 应用案例 Rally 安装 Rally 使用 Rally 架构 Rally Plugin 分析与实现 程序入口 执行 rally task ...
- Android下Native的so编译:使用cmakelists.txt
android studio的CMakeLists.txt写好后,在Studio中编译没问题,在命令编译时则需要配置很多参数才能成功 示例CMakeLists.txt文件: cmake_minimum ...
- FreeMarker开发-数据模型
FreeMarker用于处理模板的数据模型是哈希表,也就是一个树状结构的name-value对.如下: (root)|+- string="string"| +- map| || ...
- Java ——扩展:内部类 匿名内部类 IO file 设计模式
内部类的拓展 定义类or方法内部的类 最外层的类只能使用public和默认修饰 class Demo { class A { } public static void main(String[] ar ...
- C++——堆、栈与内存管理
简介 Stack,是存在于某作用域(scope) 的一块内存空间(memory space).例如当你调用函数,函数本身即会形成一个stack 用來放置它所接收的参数,以及返回地址.在函数本体(fun ...
- java8-----lambda语法
// -----lambda语法1------ https://www.baidu.com/link?url=6iszXQlsmyaoWVZMaPs3g8vLRQXzdzTnKzQYTF8lg-5QQ ...
- 剑指Offer编程题(Java实现)——反转链表
题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路一 使用头插法迭代进行反转 实现 /* public class ListNode { int val; ListNode next = n ...