(联考)noip99
T1
T2
距离最远的一定是直径的两个端点之一。
于是把操作倒过来做,并查集维护连通块内直径的两个端点即可。
T3
矩形问题,可以考虑一手扫描线。
\(k\) 很小,所以可以用线段树维护前k小, Push_up的时候归并合并(类似归并排序的一个玩意),然后就可以求出每一行有多少个male monkey,多少个female monkey,于是这题没了。
离线处理询问,可以做到 \(O(1)\) 回答,在线多带个 \(\log\) 。
Code
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
using std::sort;
using std::pair;
using std::vector;
#define re register
#define x(p) p.first
using std::make_pair;
#define y(p) p.second
#define make make_pair
const int MAX = 3e5+3;
using std::lower_bound;
#define long long long
#define scanf oma=scanf
typedef pair<int,int> my;
#define pack emplace_back
#define freopen file=freopen
int oma;
FILE* file;
namespace some
{
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
bool w=0; s=0; char ch=getchar();
while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
return s=w?-s:s,*this;
}
}cin;
long res[MAX];
int n,m,c,k,q;
long pre[MAX][2];
vector<pair<my,int>>w[MAX];
#define debug(s) printf("%s\n",s)
auto min = [](int a,int b) { return a<b?a:b; };
}using namespace some;
namespace Data_Structures
{
struct Segment_Tree
{
struct data
{
int lazy;
vector<my>k;
}st[MAX<<2];
#define ls(p) p<<1
#define rs(p) p<<1|1
#define k(p) st[p].k
#define mid (l+r>>1)
my rec[MAX<<1];
void Push_up(int p,int pos = 0,int cnt = 0)
{
k(p).clear();
for(auto z : k(ls(p)))
{
while(pos<=k(rs(p)).size()-1&&k(rs(p))[pos]<=z)
{ rec[++cnt] = (k(rs(p))[pos++]); }
rec[++cnt] = (z);
}
while(pos<=k(rs(p)).size()-1)
{ rec[++cnt] = (k(rs(p))[pos++]); }
k(p).pack(rec[1]);
for(re int i=2; i<=cnt; i++)
{
my z = rec[i];
if(x(k(p)[k(p).size()-1])==x(z))
{ y(k(p)[k(p).size()-1]) += y(z); }
else
{ k(p).pack(z); }
}
while(k(p).size()-1>k)
{ k(p).pop_back(); }
}
void build(int p,int l,int r)
{
if(l==r)
{ k(p).pack(make(0,1)); return ; }
build(ls(p),l,mid),build(rs(p),mid+1,r);
Push_up(p);
}
void Push_down(int p)
{
if(st[p].lazy)
{
for(re int i=0; i<k(ls(p)).size(); i++)
{ x(k(ls(p))[i]) += st[p].lazy; }
for(re int i=0; i<k(rs(p)).size(); i++)
{ x(k(rs(p))[i]) += st[p].lazy; }
st[ls(p)].lazy += st[p].lazy,st[rs(p)].lazy += st[p].lazy,st[p].lazy = 0;
}
}
void modify(int p,int l,int r,int lp,int rp,int val)
{
if(lp<=l&&r<=rp)
{
st[p].lazy += val;
for(re int i=0; i<k(p).size(); i++)
{ x(k(p)[i]) += val; }
return ;
}
Push_down(p);
if(lp<=mid)
{ modify(ls(p),l,mid,lp,rp,val); }
if(rp>mid)
{ modify(rs(p),mid+1,r,lp,rp,val); }
Push_up(p);
}
}Tree;
}using namespace Data_Structures;
namespace OMA
{
auto main = []() -> signed
{
//#define local
#ifdef local
debug("look here!if you want submit,please closed this");
freopen("node.in","r",stdin); freopen("my.out","w",stdout);
#endif
freopen("army.in","r",stdin); freopen("army.out","w",stdout);
cin >> n >> m >> c >> k >> q;
for(re int i=1,x1,y1,x2,y2; i<=c; i++)
{ cin >> x1 >> y1 >> x2 >> y2; w[x1].pack(make(make(y1,y2),1)),w[x2+1].pack(make(make(y1,y2),-1)); }
Tree.build(1,1,m);
for(re int i=1; i<=n; i++)
{
for(auto z : w[i])
{ Tree.modify(1,1,m,x(x(z)),y(x(z)),y(z)); }
for(auto z : Tree.k(1))
{
if(x(z)<k)
{ res[i] += y(z); }
else
{ break ; }
}
res[i] = min(res[i],m-res[i]); //printf("res=%lld\n",res[i]);
}
sort(res+1,res+1+n);
for(re int i=1; i<=n; i++)
{ pre[i][0] = pre[i-1][0]+res[i],pre[i][1] = pre[i-1][1]+res[i]*res[i]; }
for(re int i=1,x,y,z,p; i<=q; i++)
{
cin >> x >> y; z = y/2;
p = lower_bound(res+1,res+1+n,z)-res;
if(n-p+1>=x)
{ printf("%lld\n",1ll*x*z*(y-z)); }
else
{ printf("%lld\n",1ll*(n-p+1)*z*(y-z)+y*(pre[p-1][0]-pre[n-x][0])-(pre[p-1][1]-pre[n-x][1])); }
}
return 0;
};
}
signed main()
{ return OMA::main(); }
T4
不会,咕...