「清华集训 2017」某位歌姬的故事

2024-04-03 07:32

本文主要是介绍「清华集训 2017」某位歌姬的故事,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接

问题分析

吐槽一下这个预处理比DP还长的题……

首先对限制从小到大排序,然后不难发现对于每一种大小限制都是独立的。离散后考虑\(F[i][j]\)表示以\(i\)结尾,上一个音高为限制大小的位置\(j\)的方案种数。不难发现对于一些右端点相同的限制,左端点最右的限制才有效。这样就可以\(n^2\)动规了。

由于要离散化,所以细节很多。

参考程序

程序没有显式的离散化,并且大量使用结构体,所以又慢又长

#include <bits/stdc++.h>
#define LL long long
using namespace std;void Work();
int main() { int TestCases; scanf( "%d", &TestCases ); for( ; TestCases--; ) Work(); return 0; }const int Mod = 998244353;
const int MaxQ = 510;
struct seg {int Left, Right;seg() {}seg( int _Left, int _Right ) : Left( _Left ), Right( _Right ) {}
};
inline bool Cmp1( const seg X, const seg Y ) { return X.Left < Y.Left || X.Left == Y.Left && X.Right < Y.Right; }
struct query {seg Seg; int High;inline void Read() { scanf( "%d%d%d", &Seg.Left, &Seg.Right, &High ); return; }inline bool operator < ( const query Other ) const { return High < Other.High || High == Other.High && Cmp1( Seg, Other.Seg ); }
};
int Temp1[ MaxQ << 1 ], Temp2[ MaxQ << 1 ];
struct member {int Size, High; seg Seg[ MaxQ << 1 ];inline void Clear() { memset( Seg, 0, sizeof( Seg ) ); Size = High = 0; return; }inline void Import( const query Other ) { Clear(); Size = 1; High = Other.High; Seg[ Size ] = Other.Seg; return; }inline void Add( const query Other ) { Seg[ ++Size ] = Other.Seg; return; }inline void Copy( int Left, int Right ) { if( Left > Right ) return; ++Size; Seg[ Size ].Left = Left; Seg[ Size ].Right = Right; return; }void Unique( member &Goal ) {Goal.Clear(); Goal.High = High; int CoverNum = 0;for( int i = 1; i <= Size; ++i ) Temp1[ i ] = Seg[ i ].Left, Temp2[ i ] = Seg[ i ].Right;sort( Temp1 + 1, Temp1 + Size + 1 ); sort( Temp2 + 1, Temp2 + Size + 1 );int Link1 = 1, Link2 = 1, Last = 0;for( ; Link1 <= Size && Link2 <= Size; ) {if( Temp1[ Link1 ] <= Temp2[ Link2 ] ) {if( CoverNum ) Goal.Copy( Last, Temp1[ Link1 ] - 1 );Last = Temp1[ Link1++ ]; ++CoverNum;} else {if( CoverNum ) Goal.Copy( Last, Temp2[ Link2 ] );Last = Temp2[ Link2++ ] + 1; --CoverNum;}}for( ; Link1 <= Size; ) { if( CoverNum ) Goal.Copy( Last, Temp1[ Link1 ] - 1 ); Last = Temp1[ Link1++ ]; ++CoverNum; }for( ; Link2 <= Size; ) { if( CoverNum ) Goal.Copy( Last, Temp2[ Link2 ] ); Last = Temp2[ Link2++ ] + 1; ++CoverNum; }return;}void Delete( const member Done, member &Collect ) {Collect.Clear(); Collect.High = High;int Link1 = 1, Link2 = 1;for( ; Link1 <= Size && Link2 <= Done.Size; ) {if( Done.Seg[ Link2 ].Left > Seg[ Link1 ].Right ) { Collect.Copy( Seg[ Link1 ].Left, Seg[ Link1 ].Right ); ++Link1; continue;}if( Done.Seg[ Link2 ].Right < Seg[ Link1 ].Left ) { ++Link2; continue; }if( Done.Seg[ Link2 ].Left <= Seg[ Link1 ].Left && Seg[ Link1 ].Right <= Done.Seg[ Link2 ].Right ) { ++Link1; continue; }if( Seg[ Link1 ].Left <= Done.Seg[ Link2 ].Left && Done.Seg[ Link2 ].Right <= Seg[ Link1 ].Right ) {Collect.Copy( Seg[ Link1 ].Left, Done.Seg[ Link2 ].Left - 1 ); Seg[ Link1 ].Left = Done.Seg[ Link2 ].Right + 1;++Link2; continue;}if( Seg[ Link1 ].Left < Done.Seg[ Link2 ].Left ) { Collect.Copy( Seg[ Link1 ].Left, Done.Seg[ Link2 ].Left - 1 ); ++Link1; continue; }if( Seg[ Link1 ].Left > Done.Seg[ Link2 ].Left ) { Seg[ Link1 ].Left = Done.Seg[ Link2 ].Right + 1; ++Link2; continue; }}for( ; Link1 <= Size; ++Link1 ) Collect.Copy( Seg[ Link1 ].Left, Seg[ Link1 ].Right );return;}void Union( member Other ) {member Ans; Ans.Clear();int Link1 = 1, Link2 = 1;for( ; Link1 <= Size && Link2 <= Other.Size; ) {if( Seg[ Link1 ].Left < Other.Seg[ Link2 ].Left ) Ans.Seg[ ++Ans.Size ] = Seg[ Link1++ ];else Ans.Seg[ ++Ans.Size ] = Other.Seg[ Link2++ ];}for( ; Link1 <= Size; ) Ans.Seg[ ++Ans.Size ] = Seg[ Link1++ ];for( ; Link2 <= Other.Size; ) Ans.Seg[ ++Ans.Size ] = Other.Seg[ Link2++ ];Size = 1; Seg[ 1 ] = Ans.Seg[ 1 ];for( int i = 2; i <= Ans.Size; ++i )if( Seg[ Size ].Right + 1 == Ans.Seg[ i ].Left ) Seg[ Size ].Right = Ans.Seg[ i ].Right;else Seg[ ++Size ] = Ans.Seg[ i ];return;}
};
int n, Q, A, Ans;
query Query[ MaxQ ];
member Done, Now, Seperate, Collect;
int F[ MaxQ << 1 ][ MaxQ << 1 ], Before[ MaxQ << 1 ];
inline int FastPow( int a, int x ) { if( x <= 0 ) return 1; int Ans = 1; for( ; x; x >>= 1, a = 1ll * a * a % Mod ) if( x & 1 ) Ans = 1ll * Ans * a % Mod; return Ans; }
inline bool Cmp2( query X, query Y ) { return X.Seg.Right < Y.Seg.Right || X.Seg.Right == Y.Seg.Right && X.Seg.Left < Y.Seg.Left; }
inline int FindGreater( int x ) { for( int i = 1; i <= Collect.Size; ++i ) if( Collect.Seg[ i ].Left >= x ) return i; return Collect.Size + 1; }
inline int FindFewer( int x ) { for( int i = Collect.Size; i >= 1; --i ) if( Collect.Seg[ i ].Right <= x ) return i; return 0LL; }int Dp( int Left, int Right ) {if( Collect.Size == 0 ) return 0LL;sort( Query + Left, Query + Right + 1, Cmp2 );for( int i = Left; i <= Right; ++i ) {Query[ i ].Seg.Left = FindGreater( Query[ i ].Seg.Left );Query[ i ].Seg.Right = FindFewer( Query[ i ].Seg.Right );if( Query[ i ].Seg.Left > Query[ i ].Seg.Right ) return 0LL;}memset( Before, 0, sizeof( Before ) );for( int i = Left; i <= Right; ++i ) Before[ Query[ i ].Seg.Right ] = max( Before[ Query[ i ].Seg.Right ], Query[ i ].Seg.Left );for( int i = 1; i <= Collect.Size; ++i ) Before[ i ] = max( Before[ i ], Before[ i - 1 ] );memset( F, 0, sizeof( F ) );F[ 0 ][ 0 ] = 1;for( int i = 1; i <= Collect.Size; ++i ) {int Fuint = FastPow( Collect.High, Collect.Seg[ i ].Right - Collect.Seg[ i ].Left + 1 );int None = FastPow( Collect.High - 1, Collect.Seg[ i ].Right - Collect.Seg[ i ].Left + 1 );Fuint = ( Fuint - None + Mod ) % Mod;for( int j = 0; j < i; ++j ) {if( j >= Before[ i ] ) F[ i ][ j ] = ( F[ i ][ j ] + 1ll * F[ i - 1 ][ j ] * None % Mod ) % Mod;F[ i ][ i ] = ( F[ i ][ i ] + 1ll * F[ i - 1 ][ j ] * Fuint % Mod ) % Mod;}}int Ans = 0;for( int i = 0; i <= Collect.Size; ++i ) Ans = ( Ans + F[ Collect.Size ][ i ] ) % Mod;return Ans;
}void Work() {scanf( "%d%d%d", &n, &Q, &A );for( int i = 1; i <= Q; ++i ) Query[ i ].Read();sort( Query + 1, Query + Q + 1 );Done.Clear();Ans = 1;for( int i = 1, j; i <= Q; i = j + 1 ) {j = i; Now.Import( Query[ j ] );for( ; j < Q && Query[ j + 1 ].High == Now.High; Now.Add( Query[ ++j ] ) );Now.Unique( Seperate );Seperate.Delete( Done, Collect );Done.Union( Collect );Ans = 1ll * Ans * Dp( i, j ) % Mod;}if( !Done.Size ) Ans = 1ll * Ans * FastPow( A, n ) % Mod; else {Ans = 1ll * Ans * FastPow( A, Done.Seg[ 1 ].Left - 1 ) % Mod;Ans = 1ll * Ans * FastPow( A, n - Done.Seg[ Done.Size ].Right ) % Mod;for( int i = 1; i < Done.Size; ++i ) Ans = 1ll * Ans * FastPow( A, Done.Seg[ i + 1 ].Left - Done.Seg[ i ].Right - 1 ) % Mod;}printf( "%d\n", Ans );return;
}

转载于:https://www.cnblogs.com/chy-2003/p/11290617.html

这篇关于「清华集训 2017」某位歌姬的故事的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/872275

相关文章

2014暑假集训搜索专题

A - 漫步校园 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Description LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划

接下来的这个故事就来自于我的先生,一个交警的口述

这可是没有过的事情。先生是个交通警察,在事故科工作已经五、六年了,对于生离死别、阴阳两隔,用他自己的话说是已经有些麻木了;不用说他,就连我,对那些卷宗里血淋淋的照片都已经有些漠然。他的办公室常有悲悲切切的人来哭诉,他却总能在复议时做到不掺杂感情。我是个爱哭的女人,偏偏先生对于眼泪早已有了职业的免疫力,他说要是每个事故他都要为每个逝者陪眼泪的话,他早就活不下去了,但是今天不同,他分明是掉过泪了。

JD 1204:农夫、羊、菜和狼的故事

OJ题目:click here~~ #define vegetable_go 0#define vegetable_come 1#define sheep_go 2#define sheep_come 3#define wolf_go 4#define wolf_come 5#define nothing_go 6#define nothing_come 7using

2017 版本的 WebStorm 永久破解

1.  在IntelliJ官网中下载 最新版本的WebStorm   下载地址:https://www.jetbrains.com/webstorm/download/#section=windows 2. 获取注册码    获取地址:http://idea.lanyus.com/   点击获取注册码,然后将注册码复制,再打开最新版的WebStorm,将注册码粘贴到激活框中就大功告

2020年数据术语的故事

点击上方蓝色字体,选择“设为星标” 回复”资源“获取更多资源 2020年整个技术圈子要说话题最多的,应该是大数据方向。新感念层出不穷,数据湖概念就是其中之一。这篇文章是关于数据仓库、数据湖、数据集市、数据中台等一些列的概念和发展进程。希望给大家带来一个全面的感知。 本文作者:Murkey学习之旅、开心自由天使 本文整理:大数据技术与架构,未经允许不得转载。 如今,随着诸如互联网以及物联网等

SparseDrive - 清华地平线开源的e2e的框架

清华地平线合作开发的e2e的框架 SparseDrive资源 论文 https://arxiv.org/pdf/2405.19620 git https://github.com/swc-17/SparseDrive 个人觉得该文章厉害的地方 纯sparse mapping, 3d detection方案, 用的检测头sparse4D V3 sparsev1v2v3基本一致,map也是稀疏检

PMP–一、二、三模–分类–14.敏捷–技巧–故事点

文章目录 技巧一模14.敏捷--术语表-自组织团队--自组织团队是一种跨职能团队,其中为实现团队目标团队成员根据需要轮换着发挥领导作用。 自组织团队的核心就是做什么事情,团队成员说了算。61、 [单选] 作为估算活动持续时间过程的一部分,项目经理促成了与产品负责人和Scrum团队的冲刺计划会议。项目经理将用户故事分解为较小的任务项,以小时为单位估算所需时间,并根据团队的能力确定冲刺待办事项列

从清华网站下载Android代码

wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar # 下载初始化包tar xvf aosp-latest.tarcd AOSPrepo sync -j4. build/envsetup.shlunch #选择一个编译目标#这里输入19make -j8

清华MEM作业-利用管理运筹学的分析工具slover求解最优解的实现 及 通过使用文件或者套节字来识别进程的fuser命令

一、清华MEM作业-利用管理运筹学的分析工具slover求解最优解的实现         最近又接触了一些线性求解的问题,以前主要都是在高中数学里接触到,都是使用笔算,最后通过一些函数式得出最小或者最大值,最近的研究生学业上接触到了一个Excel solver分析工具,对这种线性求最优解的问题感觉使用起来真是得心应手。在使用这个工具前,EXCEL里需要先装上solver工具,装起来很也简单,网上

王楠首次讲述Cocos Creator背后的故事

Cocos Creator发布至今,得到了许多开发者的支持和喜爱,甚至有小伙伴留言说:幸福来得太突然。水滴石穿,非一日之功。这款工具从诞生到问世究竟经历了怎么样的曲折,未来又会走向何方?这方面,大概没有谁比Cocos Creator制作人王楠更有发言权了。   今天不妨抽出10分钟,听听王楠的讲述,相信或多或少会对你有所启发。   开发Cocos Creator的初衷是什么?   我和几