hdu 5773 The All-purpose Zero 最长上升子序列+树状数组

题目链接:hdu 5773 The All-purpose Zero

官方题解:0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的。

     因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量。

为了保证严格递增,我们可以将每个权值S[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的。

个人看法:对于显然把所以0放进去部分我解释一下:

  • 如果0位于最长上升子序列两边,这两个零要加进去是显然的
  • 如果有一个0夹于最长上升子序列之间,那么位于LIS中0左边的数应该比0右边的数小1,而因为预处理的效果,右边的数比左边的数至少大2,所以0是可以插进去的,举个例子:1 2 3 0 4 5 6->预处理后:1 2 3 0 3 4 5,最长是1 2 3 0 4(5) 5(6),括号里是原先的数,这个例子里0是替代了原序列0右边的4
  • 有许多个0夹于LIS的,同理可得
/**************************************************************
    Problem:hdu 5773 The All-purpose Zero
    User: youmi
    Language: C++
    Result: Accepted
    Time:171MS
    Memory:3148K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
    char c; int flag = 1;
    for (c = getchar(); !(c >= ‘0‘ && c <= ‘9‘ || c == ‘-‘); c = getchar()); if (c == ‘-‘) flag = -1, n = 0; else n = c - ‘0‘;
    for (c = getchar(); c >= ‘0‘ && c <= ‘9‘; c = getchar()) n = n * 10 + c - ‘0‘; n *= flag;
}
int Pow(int base, ll n, int mo)
{
    if (n == 0) return 1;
    if (n == 1) return base % mo;
    int tmp = Pow(base, n >> 1, mo);
    tmp = (ll)tmp * tmp % mo;
    if (n & 1) tmp = (ll)tmp * base % mo;
    return tmp;
}
//***************************

int n;
const int maxn=200000+10;
int a[maxn];
int val[maxn];
int c[maxn];
int tot;
int lowbit(int x)
{
    return x&(-x);
}
void update(int temp,int x)
{
    while(x<=tot)
    {
        c[x]=Max(c[x],temp);
        x+=lowbit(x);
    }
}
int query(int x)
{
    int res=0;
    while(x)
    {
        res=Max(c[x],res);
        x-=lowbit(x);
    }
    return res;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        sc(n);
        zeros(c);
        int cnt=0;
        int tt=0;
        int u;
        rep(i,1,n)
        {
            sc(u);
            if(u==0)
                cnt++;
            else
            {
                a[tt]=u-cnt;
                val[tt]=a[tt];
                tt++;
            }
        }
        sort(val,val+tt);
        tot=unique(val,val+tt)-val;
        int ans=0;
        rep(i,0,tt-1)
        {
            int temp=lower_bound(val,val+tot,a[i])-val+1;
            int res=query(temp-1)+1;
            ans=Max(ans,res);
            update(res,temp);
        }
        printf("Case #%d: %d\n",kase,ans+cnt);
    }
}
时间: 2024-10-13 04:07:08

hdu 5773 The All-purpose Zero 最长上升子序列+树状数组的相关文章

bzoj3173 最长上升子序列 树状数组

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3173 题意:向序列中动态插入$1~n$排列元素,求出插入每个元素后最长上升子序列长度. 如Claris所言,面对这种数据结构,必有高论.如果只想着数据结构,我们可以通过平衡树动态维护序列,同时使用树状数组计算最长上升子序列. 但是我们不是猩猩不是数据结构狂人,我们毕竟还是要本着能不上树就不上树能少用数据结构就少用的原则来设计算法的. 重新考虑这个题目.本题没有要求强制在线,于是我们把整个操作

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d

hdu 5775 Bubble Sort(2016 Multi-University Training Contest 4——树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 636    Accepted Submission(s): 378 Problem Description P is a permutation of the

hdu 5249区间第k大(学习了下树状数组的搞法)

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 205    Accepted Submission(s): 70 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的K

HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

题目大意:给一个N个点M条边的无向图,有Q个询问:1.删掉a.b之间所存在的边:2.询问有多少条边,单独删掉之后a与b不再连通. 思路:脑洞大开. 对于询问,首先想到的就是a与b之间有多少桥(割边),然后想到双连通分量,然而删边是个坑爹的问题,于是我们离线倒着来,把删边变成加边. 双连通分量这种东西呢,其实缩点连起来之后,就是一棵树辣. 然后询问两个点的时候,设根到点x的距离为dep[x],a.b的最近公共祖先为lca(a, b),那么询问query(a, b) = dep[a] + dep[b

hdu 4630 树状数组+离线操作+GCD

http://acm.hdu.edu.cn/showproblem.php?pid=4630 重新认识了树状数组. 首先要记住那个树形的图,然后+或-lowbit(i)是自己根据具体问题设定的,不要死于+或者-, 树状数组的特点: 1.+lowbit(i)可以到达包含结点i的上一层父节点    所以用于值的更改 2.-lowbit(i)可以到达不包含i所代表区间的上一层父节点  所以用于值的求和---每个不相交的段加起来 3.C[i]的含义也是根据具体问题去做设定的,但是c[i]覆盖了a[i-2

hdu 4970 树状数组区间更新 思维题

http://acm.hdu.edu.cn/showproblem.php?pid=4970 好像还没有用树状数组写过区间更新,但是树状数组的确比线段树快很多,不知道跟ZKW线段树比效率怎么样: 先贴个模板: #include <cstdio> const int MAXN = 1024; int B[MAXN], C[MAXN]; #define LOWBIT(x) ((x)&(-(x))) void bit_update(int *a, int p, int d) { for (

hdu 1556Color the ball (树状数组,更新区间,查询单点)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12566    Accepted Submission(s): 6294 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气

【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers

http://acm.hdu.edu.cn/showproblem.php?pid=4267 [思路] 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x 树状数组的单点查询:求某点a的值就是求数组中1~a的和. (i-a)%k==0把区间分隔开了,不能直接套用树状数组的区间修改单点查询 这道题的K很小,所以可以枚举k,对于每个k,建立k个树状数组,所以一共建立55棵树 所以就可以多建几棵树..然后就可以转换为成段更新了~~ [AC] 1 #include