[乱搞 树状数组] BZOJ 4548 小奇的糖果 && BZOJ 3658 Jabberwocky

跟悬线法有点像

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005;

namespace BIT{
	#define lowbit(x) ((x)&-(x))
	int maxn,c[N];
	inline void init(int n){
		maxn=n; cl(c);
	}
	inline void add(int x,int r){
		for (int i=x;i<=maxn;i+=lowbit(i))
			c[i]+=r;
	}
	inline int sum(int x){
		int ret=0;
		for (int i=x;i;i-=lowbit(i))
			ret+=c[i];
		return ret;
	}
	inline int sum(int l,int r){
		if (r<l) return 0;
		return sum(r)-sum(l-1);
	}
}

struct abcd{
	int x,y,w;
	int idx;
	int rx;
}a[N];

bool cmpx(abcd A,abcd B){
	return A.x<B.x;
}

bool cmpy(abcd A,abcd B){
	return A.y<B.y;
}

int sx[N],icnt;

inline int Bin(int x){
	return lower_bound(sx+1,sx+icnt+1,x)-sx;
}

int n,K,ans;
int pos[N],last[N];
int l[N],r[N];

inline void Solve()
{
	using namespace BIT;
	int idx,lst;
	init(icnt); cl(last);
	for (int i=1;i<=n;i++) add(a[i].x,1);
	for (int i=1;i<=n;i++) l[i]=0,r[i]=n+1;
	sort(a+1,a+n+1,cmpx);
	pos[0]=0; pos[n+1]=icnt+1;
	for (int i=1;i<=n;i++){
		a[i].rx=i; pos[i]=a[i].x;
		lst=last[a[i].w]; last[a[i].w]=i;
		l[i]=lst; if (lst) r[lst]=i;
		ans=max(ans,sum(a[lst].x+1,a[i].x-1));
	}
	for (int i=1;i<=K;i++)
		ans=max(ans,sum(a[last[i]].x+1,icnt));
	sort(a+1,a+n+1,cmpy);
	for (int i=1,j=1;i<=n;i++)
	{
		while (j<=n && a[i].y==a[j].y) add(a[j++].x,-1);
		ans=max(ans,sum(pos[l[a[i].rx]]+1,pos[r[a[i].rx]]-1));
		if (r[a[i].rx]) l[r[a[i].rx]]=l[a[i].rx];
		if (l[a[i].rx]) r[l[a[i].rx]]=r[a[i].rx];
		r[a[i].rx]=l[a[i].rx]=0;
	}
}

int main()
{
	int Q;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
	{
		icnt=0; ans=0;
		read(n); read(K);
		for (int i=1;i<=n;i++)
			read(a[i].x),read(a[i].y),read(a[i].w),sx[++icnt]=a[i].x;
		sort(sx+1,sx+icnt+1);
		icnt=unique(sx+1,sx+icnt+1)-sx-1;
		for (int i=1;i<=n;i++)
			a[i].x=Bin(a[i].x),pos[i]=a[i].x;
		Solve();
		for (int i=1;i<=n;i++) a[i].y=-a[i].y;
		Solve();
		printf("%d\n",ans);
	}
	return 0;
}
时间: 2024-10-12 17:22:50

[乱搞 树状数组] BZOJ 4548 小奇的糖果 && BZOJ 3658 Jabberwocky的相关文章

【10.22校内测试】【二分】【二分图】【很像莫队的乱搞/树状数组】

Solution 谁能想到这道题卡读入??还卡了70pts??? 二分+$n^2$check就行了 Code #include<bits/stdc++.h> using namespace std; int n, m; int sum[2005][2005]; void read(int &x) { x = 0; char ch = getchar(); while(ch > '9' || ch < '0') ch = getchar(); while(ch >= '

bzoj 4548 小奇的糖果

bzoj 他要求不包含所有颜色,那我们可以强制某种颜色不被包含.枚举每一种颜色,然后按纵坐标从小到大排序.枚举到一个点,我们要考虑在它下面一点的线段能取的最大的区域,那么左右端点分别是之前加入了的纵坐标更小离他最近的点,这个可以用以横坐标为关键字的set找.另外要把上面没有这种点的线段与下面点构成的区域也加进来.这里只考虑了往下取,可以所有点纵坐标颠倒后再来一次,就求出所有可选的矩形区域,然后扫描线二维数点 #include<bits/stdc++.h> #define LL long lon

POJ2828 Buy Tickets[树状数组第k小值 倒序]

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 19012   Accepted: 9442 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue… The Lunar New Year wa

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度

【BZOJ-4548&amp;3658】小奇的糖果&amp;Jabberwocky 双向链表 + 树状数组

4548: 小奇的糖果 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 103  Solved: 47[Submit][Status][Discuss] Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾 起多少糖果,使得获得的糖果并不包含所有的颜色. Input 包含多组测试数据,第一行输入一个正整数 T 表示测试数据组数. 接下来 T 组测试数据,对于每组测试数据,第

BZOJ 3787 Gty的文艺妹子序列 分块+树状数组

题目大意:带修改.强制在线的区间逆序对 将之前3744TLE了的某个做法重写了一发 把其中一些预处理改成了树状数组 不得不说树状数组常数还是小啊 令g[i][j](i<=j)表示第i块中的元素与第i~j块中的元素之间的逆序对数 第一维暴力第二维树状数组维护前缀和 equals[i][j]表示前i块之内j的数量 这个直接暴力即可 smaller[i][j]表示前i块之内小于等于j的数的数量 第一维暴力第二维树状数组 修改时都维护一遍 查询时 首先我们把区间分为三块 令A为左侧零碎部分 B为中间成块

hdu 4911 求逆序对数+树状数组

http://acm.hdu.edu.cn/showproblem.php?pid=4911 给定一个序列,有k次机会交换相邻两个位置的数,问说最后序列的逆序对数最少为多少. 实际上每交换一次能且只能减少一个逆序对,所以问题转换成如何求逆序对数. 归并排序或者树状数组都可搞 树状数组: 先按大小排序后分别标号,然后就变成了求1~n的序列的逆序数,每个分别查询出比他小的用i减,在把他的值插入即可 #include <cstdio> #include <cstdlib> #includ

树状数组小结

树状数组基本概念 树状数组也是进行区间操作的常用数据结构.树状数组适用于单个元素经常修改,而且还反复求部分的区间和的情况. 对于数组a,构造一个新的数组C,使得C[i] = a[i-2^k+1] + a[i-2^k+2] + ... + a[i]; (1) i >= 1: (2) k为i在二进制表示下末尾的连续的0的个数,2^k = i&(-i),通常用lowbit(i)表示i对应的2^k,lowbit(i) = 2^k = i&(-i): 则数组C为数组a的树状数组. 数组数组的结

树状数组与线段树

一:树状数组 树状数组是对一个数组改变某个元素和求和比较实用的数据结构.两中操作都是O(logn). 需求:有时候我们需要频繁地求数组的前k项和或者求数组从小标i到j的和,这样每次最坏情况下的时间复杂度就会为O(N),这样效率太低了.而树状数组主要就是为了解决这样一个问题.树状数组在求和及修改都可以在O(lgN)时间内完成. 树状数组需要额外维护一个数组,我们设为C[N],原数组为A[N], 其中每个元素C[i]表示A[i-2^k+1]到A[i]的和,这里k是i在二进制时末尾0的个数.注意通过位