学军NOIP2016模拟赛1

GTMD这么水的一套题没有AK

T1:妥妥的二分答案,贪心check。

T2:问题可以转化为最长上升(还是下降我记不住了)子序列。

T3:发现点被覆盖上的顺序是一定的。求出这个顺序,第一个操作在线段树上二分,第二个操作是找到这个点最上面那个有人的点,把他的状态变为没人。

P.S.常数这么大也能过。。。

然而一开始260为什么呢。。

anc开的maxv*20还TMfor到了20。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 100500
#define eps 1e-6
#define inf 0x7f7f7f7f7f7f7f7fLL
using namespace std;
long long n,h,x;
double l=1,r=2000000000,ans;
vector <long long> v[maxn];
bool check(double x)
{
    double ret=0;
    for (long long i=1;i<=n;i++)
    {
        double mx=-inf;
        for (long long j=1;j<=h;j++)
            mx=max(mx,(double)v[i][j]-x*j);
        ret+=mx;
    }
    if (ret>=0) return true;
    return false;
}
int main()
{
    scanf("%lld%lld",&n,&h);
    for (long long i=1;i<=n;i++)
    {
        v[i].push_back(0);
        for (long long j=1;j<=h;j++)
        {
            scanf("%lld",&x);
            v[i].push_back(v[i][j-1]+x);
        }
    }
    while (r-l>=eps)
    {
        double mid=(l+r)/2;
        if (check(mid)) {ans=l=mid;}
        else r=mid;
    }
    printf("%.4lf\n",ans);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100500
using namespace std;
int n,a[maxn],b[maxn],x,t[maxn],ans=0,ret=0;
int lowbit(int x) {return (x&(-x));}
void modify(int x,int val)
{
    for (int i=x;i<=n;i+=lowbit(i))
        t[i]=max(t[i],val);
}
int ask(int x)
{
    int ret=0;
    for (int i=x;i>=1;i-=lowbit(i))
        ret=max(ret,t[i]);
    return ret;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        b[x]=i;
    }
    for (int i=1;i<=n;i++)
    {
        ret=ask(n-b[a[i]]+1);
        ans=max(ans,ret+1);
        modify(n-b[a[i]]+1,ret+1);
    }
    printf("%d\n",ans);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxv 100500
using namespace std;
int n,m,x,y,g[maxv],nume=1,op,dfn[maxv],fdfn[maxv],times=0,dis[maxv],anc[maxv][20];
int root,tot=0,ls[maxv<<2],rs[maxv<<2],sum[maxv<<2],lazy[maxv<<2];
vector <int> v[maxv];
void dfs(int x,int fath)
{
    for (int i=0;i<v[x].size();i++)
    {
        int pos=v[x][i];
        if (pos==fath) continue;
        anc[pos][0]=x;dis[pos]=dis[x]+1;
        dfs(pos,x);
    }
    dfn[x]=++times;fdfn[times]=x;
}
void get_table()
{
    for (int i=1;i<=19;i++)
        for (int j=1;j<=n;j++)
            anc[j][i]=anc[anc[j][i-1]][i-1];
}
void build(int &now,int left,int right)
{
    now=++tot;sum[now]=right-left+1;lazy[now]=0;
    if (left==right) return;
    int mid=left+right>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void pushdown(int now)
{
    if (!lazy[now]) return;
    lazy[ls[now]]=lazy[rs[now]]=lazy[now];
    sum[ls[now]]=sum[rs[now]]=0;lazy[now]=0;
}
void pushup(int now)
{
    sum[now]=sum[ls[now]]+sum[rs[now]];
}
int ask1(int now,int left,int right,int x)
{
    pushdown(now);
    if (left==right) return left;
    int mid=left+right>>1,k=sum[ls[now]];
    if (x<=k) return ask1(ls[now],left,mid,x);
    else return ask1(rs[now],mid+1,right,x-k);
}
void modify1(int now,int left,int right,int l,int r)
{
    if ((left==l) && (right==r))
    {
        lazy[now]=1;sum[now]=0;
        return;
    }
    int mid=left+right>>1;
    if (r<=mid) modify1(ls[now],left,mid,l,r);
    else if (l>=mid+1) modify1(rs[now],mid+1,right,l,r);
    else
    {
        modify1(ls[now],left,mid,l,mid);
        modify1(rs[now],mid+1,right,mid+1,r);
    }
    pushup(now);
}
int ask2(int now,int left,int right,int pos)
{
    pushdown(now);
    if (left==right) return sum[now];
    int mid=left+right>>1;
    if (pos<=mid) return ask2(ls[now],left,mid,pos);
    else return ask2(rs[now],mid+1,right,pos);
}
void modify2(int now,int left,int right,int pos)
{
    pushdown(now);
    if (left==right) {sum[now]=1;return;}
    int mid=left+right>>1;
    if (pos<=mid) modify2(ls[now],left,mid,pos);
    else modify2(rs[now],mid+1,right,pos);
    pushup(now);
}
void work1()
{
    int pos=ask1(root,1,n,x);
    printf("%d\n",fdfn[pos]);
    modify1(root,1,n,1,pos);
}
void work2()
{
    int ret=x;
    for (int i=19;i>=0;i--)
    {
        if (!anc[ret][i]) continue;
        if (!ask2(root,1,n,dfn[anc[ret][i]])) ret=anc[ret][i];
    }
    printf("%d\n",dis[x]-dis[ret]);
    modify2(root,1,n,dfn[ret]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&x,&y);
        v[x].push_back(y);v[y].push_back(x);
    }
    for (int i=1;i<=n;i++) sort(v[i].begin(),v[i].end());
    dfs(1,0);get_table();
    build(root,1,n);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&op,&x);
        if (op==1) work1();
        else work2();
    }
    return 0;
}
时间: 2024-12-20 10:25:47

学军NOIP2016模拟赛1的相关文章

NOIP2016 模拟赛

——那些年,我们学过的文化课 考场得分140分. 背单词 (word.c/cpp/pas) [题目描述] fqk 退役后开始补习文化课啦, 于是他打开了英语必修一开始背单 词. 看着满篇的单词非常头疼, 而每次按照相同的顺序背效果并不好, 于是 fqk 想了一种背单词的好方法!他把单词抄写到一个 n 行 m 列的 表格里,然后每天背一行或者背一列.他的复习计划一共有 k 天,在 k 天后, fqk 想知道,这个表格中的每个单词,最后一次背是在哪一 天呢? [输入格式] 第一行三个整数 k m n

【NOIP2016模拟赛(五)】Jams 倒酒(pour) - 扩展欧几里得

Problem Pour 题目大意 一个人要用两个装水量一定的杯子互相倒水,求最后能搞出来最少的水量是多少以及倒的次数. Solution 我们不知道为什么突然就发现了这个最少的水量一定就是最大公约数. 然后我们不知道为什么突然就想到了扩展欧几里得算法. 首先我们有$ax + by =\gcd(a,b)$ 然后我们就可以想到,这个x和y其实就是倒的次数嘛. 于是就用扩欧算出来了x,y.但是还没有完,题目要求我们求出最小的b. 那么我们知道,只要我们找到一组特殊的解 x0 和 y0,我们就可以用

【noip模拟赛】 射击

这题似乎是什么安阳一中的模拟题,不管了,反正是学长出的noip模拟赛里面的题目.... 射击(shoot.pas/.c/.cpp) 时间限制:1s,内存限制128MB 题目描述: 据史书记载,对越反击战时期,有位中国侦察兵,他的代号叫814.一天他执行狙击任务,他的任务地区是n座恰巧在一条直线上的山.这些山所在直线恰巧为东西走向,山从东到西依次编号为1~n.一天814隐藏在编号为k的山上,每座山上都有1个目标. 814也非常的厉害,任务结束时杀了很多人,可是史书中只记载了两点: 1:814一定攻

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

记20180121模拟赛 【迁移至洛谷博客】

昨天的模拟赛考的不行啊. 和yy同学赶到考场,已经迟到了5分钟,看见zcr同学正在认真地敲着代码,心里就很慌.看见十分钟以后老卜才到,心里有了点安慰. 拿到题目,第一题.一开始看见题目十分激动,直接忽视了题目给的方程里面的绝对值.于是非常高兴地写了一个前缀最小值的处理,然后发现不对,仔细读题,看到绝对值,差点晕过去.加一个绝对值,那意味着我们的任务是在比该数大的数里面找最小值,比它小的数里找最大值.那么第一反应就想到了当年的推销员的堆,建一个小根堆维护比他大的数,建一个大根堆维护比它小的数,然后

ZROI 普及组模拟赛02总结

ZROI 普及组模拟赛02总结 先放[网址][http://zhengruioi.com/contest/96] 可能是有一段时间没有打这种正式的比赛了,今天打的很奇怪... T1 模拟水题 既然是普及组模拟赛T1还是比较良心的 20分钟就过掉了 T2 <论不仔细观察题目导致的惨案> 没有发现莫尔斯电码非常的全 所以应该枚举哪些不行,而不是枚举26个字母 但是根据计算\(2*26*1e6\)也能跑过去啊 不知道为什么就是超时了... 最可笑的是还卡了20min的常数,还自己造了几组1e6的数据

模拟赛题目选集

A. [线上训练13]二叉树 题解:贪心,先求出这两个序列,i在第一个序列位置为\(a[i]\),第二个为\(b[i]\),如果\(a[i] > b[i]\), \(ans += 2^{a[i]-b[i]}\) #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<set> #inclu

2016-11-15NOIP模拟赛

AM学军OJ T1 暴力 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long LL; 6 const int N = 2000000 + 10; 7 8 int len, power; 9 10 int get_next(int x) { 11 return x / 10 + x % 10 * power; 12 } 13 14 int vis[N], clk; 15 16 LL calc(int l

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我