BZOJ4548少し奇妙キャンディ

タイトル
\(X \)ディスクリート、\(Y \)セットを開くために、各色ごとに、降順です。
我々はすべての色が含まれているので、それを含めることができない特定の色を強制する必要はありませんので。
矩形は、その下側境界(取らない)のために選択された場合、特定の点については、横軸の左端は右端の前駆体は、横軸(対象外である)の後継です。
あなたは、前駆体の後継者を使用することができますバランスのとれたツリーリストまたはセットメンテナンス、ツリーの範囲内で計算点の数は、アレイを維持するために使用することができます。
私たちは、その後、上記の各列挙するために、次から行く\(のy \)この座標\(のy \)の回答の座標を計算し、それを追加するために、各点のために\(セット\)を、フェンウィックの木。
最後に、無列挙長方形の枠線の下で。
後にやって、その後、ボトムアップから、再びそれを行います。

using namespace std;
const int N=100007;
set<int>s[N];
struct node{int x,y,col;}a[N];
int n,m,b[N],t[N],ans;
int operator<(node a,node b){return a.y<b.y;}
int read(){int x;scanf("%d",&x);return x;}
int max(int a,int b){return a>b? a:b;}
void add(int p){for(;p<=n;p+=p&-p) ++t[p];}
int query(int p){int sum=0;for(;p;p-=p&-p) sum+=t[p];return sum;}
void solve()
{
    int i,j,k,c;
    set<int>::iterator it;
    memset(t,0,sizeof t);
    for(i=1;i<=m;++i) s[i].clear(),s[i].insert(0),s[i].insert(n+1);
    for(i=j=1;i<=n;i=j)
    {
        while(j<=n&&a[j].y==a[i].y) ++j;
        for(k=i;k<j;++k) c=a[k].col,ans=max(ans,query(*s[c].lower_bound(a[k].x)-1)-query(*--s[c].upper_bound(a[k].x)));
        for(k=i;k<j;++k) add(a[k].x),s[a[k].col].insert(a[k].x);
    }
    for(i=1;i<=m;++i) for(it=s[i].begin();(*it)^(n+1);) j=*it,ans=max(ans,query(*++it-1)-query(j));
}
int main()
{
    for(int i,T=read();T;--T)
    {
        n=read(),m=read(),ans=0;
        for(i=1;i<=n;++i) b[i]=a[i].x=read(),a[i].y=read(),a[i].col=read();
        sort(a+1,a+n+1),sort(b+1,b+n+1);
        for(i=1;i<=n;++i) a[i].x=lower_bound(b+1,b+n+1,a[i].x)-b;
        solve();
        for(i=1;i<=n>>1;++i) swap(a[i],a[n-i+1]);
        solve(),printf("%d\n",ans);
    }
}

おすすめ

転載: www.cnblogs.com/cjoierShiina-Mashiro/p/11525767.html