[考试总结]noip模拟31
三个 XIN 算法就打上去了,其他真的啥思路都没有。
然后期望得分实际上就是 \(\color{red}0\)
然而战神还是一场至少一个正解,然后沈队只交一个代码,然而 \(\color{green}{AC}\)
然后这个题目的答案大小还是很简单,然而就是这个sb字典序难搞。。。
然后第二题直接(学长skyh语录)冲上一个 XIN 队,然后 \(n^n\),然而理论上一个点都过不了。。。
然后认为自己的 \(T3\) 能水上 \(25pts\),然而谁知道出题人不是人,上来 \(m \leq 10\) ,然而 \(n \leq 1000000\)。
然后抱 \(\color{red}0\)
生气。。。。。。。。。。。
Game
我们首先可以很快地算出答案。
我们建一颗 权值线段树 来维护答案,然后建完树的 \(t[1].s\) 就已经是那个长度的答案了。
之后我们开始考虑 二分答案,每次删去一个节点进行尝试,之后查看答案是否变化,如果不变化,则可行。
重复这样的操作,记录答案。
然后 \(std\) 上的 \(multiset\) 完全没有必要,一个桶解决。
然后这个题目的线段树可以 \(zkw\),然后快一倍!!!!!
然而我没打。。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
#define debug cout<<"debug"<<endl
#define enum(x) cout<<#x" = "<<x<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
{
register type s = 0; register int f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return x = s * f,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
class xin_segment
{
protected:
#define ls(fa) (fa << 1)
#define rs(fa) (fa << 1 | 1)
inline void up(int fa)
{
register int temp = std::min(t[rs(fa)].s1,t[ls(fa)].s2);
t[fa].s = t[ls(fa)].s + t[rs(fa)].s + temp;
t[fa].s1 = t[ls(fa)].s1 + t[rs(fa)].s1 - temp;
t[fa].s2 = t[ls(fa)].s2 + t[rs(fa)].s2 - temp;
}
public:
class xin_tree{public:int s,s1,s2;}t[maxn];
void modify(int fa,int l,int r,int pos,int val1,int val2)
{
if(l == r) return t[fa].s1 += val1,t[fa].s2 += val2,void();
register int mid = l + r >> 1;
if(pos <= mid) modify(ls(fa),l,mid,pos,val1,val2);
else modify(rs(fa),mid+1,r,pos,val1,val2);
up(fa);
}
}t;
int a[maxn],b[maxn],n;
int maxx = -inf;
int ton[maxn];
inline short main()
{
io >> n;
try(i,1,n) io >> a[i],maxx = std::max(maxx,a[i]);
try(i,1,n) io >> b[i],ton[b[i]]++,maxx = std::max(maxx,b[i]),ton[0] = std::max(ton[0],b[i]);
try(i,1,n) t.modify(1,1,maxx,a[i],0,1),t.modify(1,1,maxx,b[i],1,0);
int ans = t.t[1].s;
try(i,1,n)
{
t.modify(1,1,maxx,a[i],0,-1);
register int l = a[i] + 1,r = ton[0]; while(!ton[ton[0]]) r = --ton[0];
while(l < r)
{
register int mid = (l + r + 1) >> 1;
t.modify(1,1,maxx,mid,-1,0);
if(ans - 1 == t.t[1].s) l = mid; else r = mid - 1;
t.modify(1,1,maxx,mid,1,0);
}
t.modify(1,1,maxx,l,-1,0);
if(l <= r and ans - 1 == t.t[1].s) printf("%d ",l),ans--,ton[l]--;
else
{
t.modify(1,1,maxx,l,1,0);
l = 1; r = a[i];
while(l < r)
{
register int mid = ( l + r + 1) >> 1;
t.modify(1,1,maxx,mid,-1,0);
if(ans == t.t[1].s) l = mid; else r = mid - 1;
t.modify(1,1,maxx,mid,1,0);
}
t.modify(1,1,maxx,l,-1,0);
printf("%d ",l);
ton[l]--;
}
}
return 0;
}
}
signed main() {return xin::main();}
Time
我们找到最小值,然后向左或者向右放,当然要找近的。
重复这个过程。
就这??????
就这。。
然后距离可以 树状数组,然后可以 \(deque\)
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
#define enum(x) cout<<#x" = "<<x<<endl;
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
{
register type s = 0; register int f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return x = s * f,*this;
}}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
int n;
class xin_bit
{
protected:
#define lowbit(i) (i & -i)
public:
int c[maxn];
inline void add(int x,int val) {for(register int i=x;i<=n;i+=lowbit(i)) c[i] += val;}
inline int query(int x) {int ret = 0;for(register int i=x;i;i-=lowbit(i)) ret += c[i]; return ret;}
}bit;
std::deque<int>q[maxn / 10];
int maxx = -inf,ans = 0;
inline short main()
{
io >> n;
try(i,1,n)
{
register int x; io >> x; maxx = std::max(maxx,x);
q[x].push_back(i); bit.add(i,1);
}
try(i,1,maxx)
while(!q[i].empty())
{
register int x = q[i].front(),a = bit.query(x-1),y = q[i].back(),b = bit.query(n) - bit.query(y);
if(a < b) ans += a,bit.add(x,-1),q[i].pop_front();
else ans += b,bit.add(y,-1),q[i].pop_back();
}
cout<<ans<<endl;
return 0;
}
}
signed main() {return xin::main();}
Cover
子区间之间只有相互包含和不交的关系,因此它们的包含关系会构成一棵树
然后就是 树形 dp
然后我们维护一个 差分表
\(STL\)还是要用上。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
#define debug cout<<"debug"<<endl
#define enum(x) cout<<#x" = "<<x<<endl;
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
{
x = 0; register int f = 0; register char ch = gc();
while(!isdigit(ch)) {f|=ch=='-'; ch = gc();}
while( isdigit(ch)) x = (x << 1) + (x << 3) + (ch xor 48),ch = gc(); return x = f ? -x : x,*this;
}}io;
}
//#define int long long
using namespace xin_io; static const int maxn = 3e5+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
class xin_data
{
private:
friend bool operator < (xin_data x,xin_data y)
{return x.l == y.l ? x.r > y.r : x.l < y.l;}
public:
int l,r,a;
}d[maxn];
int n;
int st[maxn];
std::vector<int>vec[maxn];
std::multiset<ll>mt[maxn];
int jsq1,jsq2;
inline void merge(std::multiset<ll>&a,std::multiset<ll>&b)
{
if(a.size() < b.size()) std::swap(a,b);
std::vector<ll>temp;
for(auto i : b) temp.push_back(i + *a.begin()),a.erase(a.begin());
for(auto i : temp) a.insert(i);
}
void dfs(int x)
{
for(auto v : vec[x])
{
dfs(v);
merge(mt[x],mt[v]);
}
mt[x].insert(-d[x].a);
}
inline short main()
{
io >> n >> n;
try(i,1,n) io >> d[i].l >> d[i].r >> d[i].a;
st[++st[0]] = 0; std::sort(d+1,d+n+1);
try(i,1,n)
{
while(st[st[0]] and d[st[st[0]]].r < d[i].r) st[0]--;
// cout<<++jsq1<<" st[st[0]] = "<<st[st[0]]<<endl;
vec[st[st[0]]].push_back(i);
// cout<<++jsq2<<" st[st[0]] = "<<st[st[0]]<<endl;
st[++st[0]] = i;
}
dfs(0); ll ans = 0;
try(i,1,n)
{
if(mt[0].size())
{
ans -= *mt[0].begin();
mt[0].erase(mt[0].begin());
}
printf("%lld ",ans);
}
return 0;
}
}
signed main() {return xin::main();}