bzoj1106 树状数组

https://www.lydsy.com/JudgeOnline/problem.php?id=1106

一个叫做立方体大作战的游戏风靡整个Byteotia。这个游戏的规则是相当复杂的,所以我们只介绍他的简单规
则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置。这些元素拥有n个不同的编号,每个编号正好有两个
元素。玩家每次可以交换两个相邻的元素。如果在交换之后,两个相邻的元素编号相同,则将他们都从栈中移除,
所有在他们上面的元素都会掉落下来并且可以导致连锁反应。玩家的目标是用最少的步数将方块全部消除。

题意

贪心的想到每一对当前匹配的费用是他们之间未匹配的数字的个数。

第一个想法是每次取出费用最小的对进行匹配,每次产生r - l - 1的费用,直到全部匹配,但是这样怎么看都觉得会T,事实上每次并不需要总是取出最小的来匹配。

也就是说当状态时1234512345 678876的时候,左边和右边的操作事实上是相互独立的,先后顺序并不干扰,所以我们只要从前向后遍历,第一个和前面有匹配的数字就是当前状态的最优对数,我们直接将他消去,更新他们之间数字的费用即可。

操作用BIT维护一下就好了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 5e4 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,tmp,K;
int tree[maxn * 2];
void add(int x,int t){
    for(;x <= N * 2;x += x & -x) tree[x] += t;
}
int getsum(int x){
    int s = 0;
    for(;x > 0;x -= x & -x) s += tree[x];
    return s;
}
int vis[maxn];
int main()
{
    Sca(N);
    int cnt = 0;
    int ans = 0;
    For(i,1,N * 2){
        int x; Sca(x);
        if(!vis[x]){
            cnt++;
            vis[x] = i;
            add(i,1);
        }else{
            ans += cnt - getsum(vis[x]);
            cnt--;
            add(vis[x],-1);
        }
    }
    Pri(ans);
    #ifdef VSCode
    system("pause");
    #endif
    return 0;
}

原文地址:https://www.cnblogs.com/Hugh-Locke/p/9695434.html

时间: 2024-07-30 19:09:22

bzoj1106 树状数组的相关文章

bzoj1106([POI2007]立方体大作战tet)(树状数组)

传送门 首先要看出,对于每一对,其凑到一起所需要的操作次数是中间没被匹配的个数. 于是想到贪心,每次操作所需次数最小的. 但其实做法并不需要这么麻烦,只用从左到右扫一遍. 如果当前数字已经出现过,就统计其中未匹配的个数,同时把这一对标记为“已匹配”,就不会对后面的答案造成影响. 用树状数组维护即可,第一次出现树状数组中对应位置的权值+1,第二次出现时,累计答案,同时把前面相同的数的位置树状数组里权值-1. #include<bits/stdc++.h> #define LL long long

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

(POJ 3067) Japan (慢慢熟悉的树状数组)

Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29295   Accepted: 7902 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coas

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击

CF 313 DIV2 B 树状数组

http://codeforces.com/contest/313/problem/B 题目大意 给一个区间,问你这个区间里面有几个连续相同的字符. 思路: 表示个人用树状数组来写的...了解了树状数组的本质就行了. 当然用sum[r]-sum[l]也是可以的

Hdu5032 极角排序+树状数组

题目链接 思路:参考了题解.对询问进行极角排序,然后用树状数组维护一下前缀和即可. /* ID: onlyazh1 LANG: C++ TASK: test */ #include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; const int maxn=1010; const int maxm=10

Curious Robin Hood(树状数组+线段树)

1112 - Curious Robin Hood    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another tri

【初识——树状数组】 区间求最值

说树状数组其实是一个索引表,但是是一个特殊的,树状的索引表,它利用了二进制的一些特性. 就区间求和的要求来说: 首先我们用a[]数组来存储原始数据.然后在a[]之上构造c[]数组来作为树状数组. 如图 这个图表示,当i为奇数时,c[i]中保存的都是a[i]本身.然后,c[2]中保存了a[1], a[2],共2个,c[4]中保存的是a[1], a[2], a[3], a[4],c[6]又是保存两个,c[5]和c[6].c[8]保存8个,c[1], c[2], c[3], c[4], c[5], c