选的2015资格赛的部分题目,第二题字符串处理,第三题map计数
f f (x) = x
两次置换后回到原位
dp a->b && b->a,考虑n个数
如果它独自成对,那么就有s[n-1];
如果它与前面某个成对,首先可以有n-1个可取,然后每个都有s[n-2];
故s[n] = s[n-1] + (n-1)s[n-2];
今天他向来访者们提出一个恶俗的游戏。他和来访者们轮流往一个正多边形内放盘子。最后放盘子的是获胜者,会赢得失败者的一个吻。玩了两次以后,小度熊发现来访者们都知道游戏的必胜策略。现在小度熊永远是先手,他想知道他是否能获胜。
脑洞题,看能不能再中间放一个盘子
S[a,b] = S[b] - S[a-1]
但是这里是除法= =所以涉及乘法逆元
费马小定理:
p is prime => x^(p-1) = 1(mod p)
LL mod_pow(LL x, LL n) { LL res = 1; while(n) { if(n & 1) res = res * x % mod; x = x * x % mod; n >>= 1; } return res%mod; }
据说可以用线段树做..
度熊面前有一个全是由1构成的字符串,被称为全1序列。你可以合并任意相邻的两个1,从而形成一个新的序列。对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列
高精度fib
sort后丢到map统计
增加功能: 前缀删除和存在该前缀即可
这道题让我发现以前理解的字典树是错误的..
字典树其实是一个节点数组 tr[节点数][26],而不是指针无限扩展= =
插入单词时,到达一个节点,该节点的次数+1;删除单词时,先判断删除的这个前缀在当前字典树里是否存在,如果存在的话,得到这个单词结尾节点的次数m,然后用删除函数将路径上的每个节点都减去m。
所以解决方案是,当插入单词是,判断当前节点的次数是不是1,如果是1的话说明之前这个位置是断开的,就将当前节点之后所连接的节点次数清空。
小度熊是一个尽职尽责的程序熊,每天产出数千行的代码,代码当中存在很多判断条件。度熊想让自己代码中的这些条件不存在交集。为了简化问题,一个条件可以是一个『简单条件』或者是一个『复合条件』,简单条件由『变量』、『比较符』和『运算数』组成,其中『变量』是用小写字符表示的一串字符,『运算数』仅为整数,『运算符』包括:<、>、<=、>=、==。分别代表:小于、大于、小于等于、大于等于和等于关系。简单条件的格式固定,左边为变量名,中间为操作符,右边为数字。若干个『简单条件』中间通过英文逗号组成一个『复合条件』,各『简单条件』之间是逻辑与的关系,例如:
简单条件: a > 100
复合条件: duxiong < 1000 , a > 100
初次读题目特别像子臻老师编的那本题解里面的floyd判断闭包
但是这个题目是判断多个,而且有常数
这道题的思路是判断每个变量名的合法取值范围是否为空集
所以…就是一道模拟题?!!!…
F(x,m) 代表一个全是由数字xx组成的mm位数字。请计算,以下式子是否成立:F(x,m) mod k ≡ c
1≤x≤9
m\<= 10^{10}
0≤c
/*
双重快速幂,quickPow是x^m
calc中便是对于十进制(位数)的快速幂
偶数: F(x,m/2) * (10^(m/2)+1)
奇数: F(x,m-1) * 10 + x
*/
inline int quickPow(LL times){
int ret = 1, base = 10 % p;//base % p
while(times){
if(times & 1LL) ret = ret * base % p;
base = base * base % p;
times >>= 1;
} return ret;
};
int calc(LL x){
if(x == 1LL) return v;
int ret = calc(x >> 1LL);
ret = (ret * quickPow(x >> 1) + ret) % k;
return (x & 1LL) ? ((ret * 10 + v) % k) : ret;
};
快速幂
f[0]=1f[i]=(f[i-1]*10+x)%k
加速递推式
假设最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。
有一些同学不希望某个(些)同学排在他(她)前面
所有同学的评价分数最大和
N M <= 100000(N不能再M后面)
一直TLE在优先队列的复杂设置,很简单的思路不能清晰下来当然跪倒底.
贪心,读入N,M的时候记录N的边数和M的度数这时候不需要优先队列参与
但是这里用queue存N的边会爆内存,需要用vector
然后优先队列直接用int,把能放的放进去,每次拿堆顶元素来更新d[边]
给一组数据排序,使得相邻数乘积和最大
有一些数字固定.
N <= 16
第一次提交是DFS..写了好久真是手生,理所当然T
看到N<=16就觉得是状压DP..然而没写过QAQ
i为这会哪些数字已经被选(二进制表示)
用__builtin_popcount(i)
得到有多少个i
j为最后一个选的数字是哪一个
dp [ i | (1<
//第一个过的人的核心代码
for(int mask=0;mask<(1<1;mask++)
for(int i=0;iif(ok[mask][i])
{
int t=num[mask];
if(at[t] != -1)
{
int j=at[t];
if(mask&(1<continue;
dp[mask+(1<max(dp[mask+(1<1<true;
}
for(int j=0;jif(mask&(1<continue;
dp[mask+(1<max(dp[mask+(1<1<true;
}
}
众所周知,度度熊喜欢的字符只有两个:B和D。
今天,它发明了一种用B和D组成字符串的规则:
S(1)=BS(1)=B
S(2)=BBDS(2)=BBD
S(3)=BBDBBDDS(3)=BBDBBDD
…
S(n)=S(n-1)+B+reverse(flip(S(n-1))S(n)=S(n−1)+B+reverse(flip(S(n−1))
其中,reverse(s)reverse(s)指将字符串翻转,比如reverse(BBD)=DBBreverse(BBD)=DBB,flip(s)flip(s)指将字符串中的BB替换为DD,DD替换为BB,比如flip(BBD)=DDBflip(BBD)=DDB。
虽然度度熊平常只用它的电脑玩连连看,这丝毫不妨碍这台机器无与伦比的运算速度,目前它已经算出了S(2^{1000})S(21000)的内容,但度度熊毕竟只是只熊,一次读不完这么长的字符串。它现在想知道,这个字符串的第LL位(从1开始)到第RR位,含有的BB的个数是多少?
(1≤L≤R≤10^18)
找规律发现 S(n) = 2^n-1…
但是一方面不用高精度S(n)求不出来,另一方面需要直接构造剩下的区间
所以需要分开讨论,
在这个题解中,分类讨论:
如果L,R都在mid右边,那么可以把区间映射到mid左边,此时求B数量,相当于求D数量,因为flip操作。
如果L<=mid && R >= mid,那么可以从mid左右两边取相等长度的区间,剩下的区间在考虑是在mid的左边还是右边,如果是右边的话,就要进行映射,换为求D的数量。
所以整个算法只需要递归最多60层就可以得出解了。时间复杂度为log(R-L+1)感觉是带标志变换的二分
这个题解的思路是求出
另外,1003是dfs+线段树,1004是区间DP
安利这个题解
只能往 右且下 移动,求(1,1)到(n,m)的选择,mod 1000000007
2≤n,m≤100000
/*
1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9
1 3 6 10 15 21 28 36 45
1 4 10 20 35 56 84 120 165
1 5 15 35 70 126 210 330 495
1 6 21 56 126 252 462 792 1287
1 7 28 84 210 462 924 1716 3003
1 8 36 120 330 792 1716 3432 6435
1 9 45 165 495 1287 3003 6435 12870
*/
打表,一眼看去是a[x][y] = a[x-1][y] + a[x][y-1]
继续找规律,发现a[x][y] = c(x + y - 4, max(x, y) - 2 );
然后用组合数公式算,算除法时候忘记除逆元就模了…Wa一次
居然以为是高精度,折腾了好久反应过来是逆元….就这样吧…858名憾别今年百度之星
高精度一直不取模算法上也可以,但是目测会超时…
给出一组数(n < 8000)求每个数是多少个区间的中位数
当满足big <= (len-1)/2&& sml <= (len-1)/2
计数器+1
看别人O(n2)的算法
往左扫时候记录[l,i]l是第x小的数,cnt[i+x]++(统计一共有几个)
往右扫的时候y += cnt[i+x];也就是加上对应位置.
int x=0; cnt[n]++;
for (int j=1;i-j>0;j++)
{
if (a[i-j]
x=0;
int y=cnt[n];
for (int j=1;i+j<=n;j++)
{
if (a[i+j]
也就是说左右相比就可以了= =抓住主要矛盾.
nn个非负整数的数列与mm个区间。每个区间可以表示为l_{i},r_{i}li,ri。
它想选择其中kk个区间, 使得这些区间的交的那些位置所对应的数的和最大。
写了一个dfs..果断T
//优先队列,懒得写函数的FB少年读入变化
//sort后按照first先后排序
for (int i = 1; i <= m; i++) //到底i个区间
{
if (q.size() < k)//如果不够k个
{
q.push(-a[i].second);//把结尾丢进去(由于是负数在后面)
}
else if (-q.top() < a[i].second)//(k个)如果原来最先结尾先于现在结尾,更换
{
q.pop();
q.push(-a[i].second);
}
if (q.size() == k)
{
ans = max(ans, s[-q.top()] - s[a[i].first - 1]);//到现在这一个区间的开头
}
}
我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在L,右端点在R,那么该区间的长度为(R-L+1)
现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。
当然,由于这个问题过于简单。
我们肯定得加强一下。
我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。
第一行一个数n(1≤n≤100000)。
第二行n个正整数(1≤ai≤109),下标从1开始。
输出n行,每行一个最大乘积
第一直觉是线段树…
rmq
左右贪心扫
for (i=1;i<=n;i++)
{
l = r = i;
minn=a[i];
ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);//初始化,假设a[i]最大值
while(a[l-1]<=a[i]||a[r+1]<=a[i])
{
while(l>1)
if (a[l-1]<=a[i]&&a[l-1]>=minn)//左边的可以更新最小值
l--,ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
else break;
while(rif (a[r+1]<=a[i]&&a[r+1]>=minn)
r++,ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]); //右边的可以更新最小值
else break;
if (a[l-1]<=a[i] && a[r+1]<=a[i]) //更新
{
if (a[l-1]>a[r+1])
l--,minn=a[l],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
else
r++,minn=a[r],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
}
else if (a[l-1]<=a[i])
l--,minn=a[l],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
else if (a[r+1]<=a[i])
r++,minn=a[r],ans[r-l+1]=max(ans[r-l+1],(ll)minn*a[i]);
}//end of while
}//end of for
公元2222年,l国发生了一场战争。
小Y负责领导工人运输物资。
其中有m种物资的运输方案,每种运输方案形如l_{i},r_{i}。表示存在一种货物从l_{i}运到r_{i}。
这里有n个城市,第i个城市与第i+1个城市相连(这里1号城市和n号城市并不相连),并且从i号城市走到i+1号或者从i+1号走到ii号需要耗费1点时间。
由于高科技的存在,小Y想到了一种节省时间的好方案。在X号城市与Y号城市之间设立传送站,只要这么做,在X号城市走到Y号城市不需要耗费时间,同样的,从Y号城市走到X号城市也不需要耗费时间。
但是为了防止混乱,只能设立这么一条传送站。
现在这些运输方案同时进行,小Y想让最后到达目的地的运输方案时间最短。
第一行两个整数n,m(1≤n,m≤1000000)。
接下来mm行,每行两个整数l_{i},r_{i}(1≤li,ri≤n)
t[a][a] = 0
这么明显的二分= =居然二逼了
诶看代码到一半发现就是求树的直径啊?题解
int solve(int tmp) {
int right = Inf;
int up = Inf;
int down = -Inf;
int left = -Inf;
for (int i = 0; i < move.size(); ++i)
if (move[i].r - move[i].l > tmp) {
downdate(right, move[i].l + move[i].r + tmp);
downdate(up, move[i].l - move[i].r + tmp);
update(down, move[i].l - move[i].r - tmp);
update(left, move[i].l + move[i].r - tmp);
if (left > right || down > up) return 0;
}
return 1;
}
看上去就是一个背包啊..但是过的人实在太少了…
然后发现,是和(A)*和(B),不是和(A*B)
摆在你面前的是n道题目,第 i(1≤i≤n) 道题目能提升ai 点智力值,代码量为 bi KB,无聊值为 ci ,求至少提升m点智力值的情况下,所做题目代码量之和*无聊值之和最小为多少。
然后过了的代码都是Point(x,y)搜索的..
找了一个宏定义少的代码贴过来
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int N=805;
struct Point
{
int x,y;
};
int n,m,s,a[N],b[N],c[N];
LL Ans,val[N],v[N];
Point f[N];
Point get(LL x,LL y)
{
for(int i=1;i<=s;i++)
f[i].x=f[i].y=1e7,val[i]=(LL)1e7*(x+y);
for(int j=1;j<=n;j++)
v[j]=b[j]*x+y*c[j];
for(int j=1;j<=n;j++)
for(int k=min(m+a[j],s);k>=a[j];k--)
if(val[k-a[j]]+v[j]for(int i=m+1;i<=s;i++)
if(f[i].x*x+f[i].y*yreturn c;
}
void dfs(Point a,Point b)
{
Point c=get(a.y-b.y,b.x-a.x);
if((c.x-a.x)*(LL)(b.y-a.y)-(c.y-a.y)*(LL)(b.x-a.x)>0)
dfs(a,c),dfs(c,b);
}
int main()
{
while(cin>>n>>m)
{
s=0;
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]),s+=a[i];
Ans=1LL<<60;
Point x=get(1,0),y=get(0,1);
dfs(x,y);
printf("%I64d\n",Ans);
}
return 0;
}
Close
百度之星最好的在于可以看到大神们的头文件长什么样…
include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
stdio读写
#if ( ( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
#define lld "%I64d"
#else
#define lld "%lld"
#endif
inline void gn(long long&x){
int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
}
inline void gn(int&x){long long t;gn(t);x=t;}
inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
inline void gs(char *s){scanf("%s",s);}
inline void gc(char &c){while((c=getchar())>126 || c<33);}
inline void pc(char c){putchar(c);}
二进制处理
#define cnti(x) (__builtin_popcount(x))//1的个数
#define cntl(x) (__builtin_popcountll(x))
#define clzi(x) (__builtin_clz(x))//左起第一个1前0的个数
#define clzl(x) (__builtin_clzll(x))
#define ctzi(x) (__builtin_ctz(x))//右起第一个1之后0的个数
#define ctzl(x) (__builtin_ctzll(x))
常数
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector vpii;
const int inf=0x3f3f3f3f;
const db pi=3.14159265358979323846264338327950288L;
const db eps=1e-6;
const int mo=0;
//另一个
const int low(int x) { return x&-x; }
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 10;
函数
inline ll sqr(ll a){return a*a;}
inline db sqrf(db a){return a*a;}
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
#define per(i,a,b) for (int i=(b)-1,_ed=(a);i>=_ed;i--)
#define pw(x) ((ll(1))<<(x))
#define upmo(a,b) (((a)=((a)+(b))%mo)<0?(a)+=mo:(a))
#define mmo(a,b) (((a)=1ll*(a)*(b)%mo)<0?(a)+=mo:(a))
void getre(){int x=0;printf("%d\n",1/x);}
void gettle(){int res=1;while(1)res<<=1;printf("%d\n",res);}
template<typename T,typename S>inline bool upmin(T&a,const S&b){return a>b?a=b,1:0;}
template<typename T,typename S>inline bool upmax(T&a,const S&b){return a1:0;}
template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
template<typename N>N gcd(N a,N b){return b?gcd(b,a%b):a;}
template<typename N>inline int sgn(N a){return a>0?1:(a<0?-1:0);}//返回参数的正负
int qp(int a,ll b){int n=1;do{if(b&1)n=1ll*n*a%mo;a=1ll*a*a%mo;}while(b>>=1);return n;}
完整版
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define y0 y0z
#define y1 y1z
#define yn ynz
#define j0 j0z
#define j1 j1z
#define jn jnz
#define tm tmz
#define buli(x) (__builtin_popcountll(x))
#define bur0(x) (__builtin_ctzll(x))
#define bul2(x) (63-__builtin_clzll(x))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
#define per(i,a,b) for (int i=(b)-1,_ed=(a);i>=_ed;i--)
#define pw(x) ((ll(1))<<(x))
#define upmo(a,b) (((a)=((a)+(b))%mo)<0?(a)+=mo:(a))
#define mmo(a,b) (((a)=1ll*(a)*(b)%mo)<0?(a)+=mo:(a))
void getre(){int x=0;printf("%d\n",1/x);}
void gettle(){int res=1;while(1)res<<=1;printf("%d\n",res);}
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector vpii;
template<typename T,typename S>inline bool upmin(T&a,const S&b){return a>b?a=b,1:0;}
template<typename T,typename S>inline bool upmax(T&a,const S&b){return a1:0;}
template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
template<typename N>N gcd(N a,N b){return b?gcd(b,a%b):a;}
template<typename N>inline int sgn(N a){return a>0?1:(a<0?-1:0);}
#if ( ( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
#define lld "%I64d"
#else
#define lld "%lld"
#endif
inline void gn(long long&x){
int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
}
inline void gn(int&x){long long t;gn(t);x=t;}
inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
inline void gs(char *s){scanf("%s",s);}
inline void gc(char &c){while((c=getchar())>126 || c<33);}
inline void pc(char c){putchar(c);}
#ifdef JCVB
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
typedef long long ll;
typedef double db;
inline ll sqr(ll a){return a*a;}
inline db sqrf(db a){return a*a;}
const int inf=0x3f3f3f3f;
const db pi=3.14159265358979323846264338327950288L;
const db eps=1e-6;
另一个更全的
/*
* Package: StandardCodeLibrary.Core
* */
//引进常用的头文件并使用std名字空间;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//用于减少代码量的宏;
#define lp for(;;)
#define repf(i,a,b) for (int i=(a);i<(b);++i)
#define ft(i,a,b) for (int i=(a);i<=(b);++i)
#define fdt(i,a,b) for (int i=(a);i>=(b);--i)
#define rrepf(i,a,b) fdt(i,(a)-1,b)
#define rep(i,n) repf(i,0,n)
#define rrep(i,n) rrepf(i,n,0)
#define for_each(e,s) for (__typeof__((s).begin()) e=(s).begin();e!=(s).end();++e)
#define for_nonempty_subsets(subset,set) for (int subset=set;subset;subset=(subset-1)&(set))
#define for_in_charset(i,charset) for (cstr i=(charset);*i;i++)
#define whl while
#define rtn return
#define fl(x,y) memset((x),char(y),sizeof(x))
#define clr(x) fl(x,char(0))
#define cpy(x,y) memcpy(x,y,sizeof(x))
#define sf scanf
#define pf printf
#define vec vector
#define pr pair
#define que queue
#define prq priority_queue
#define itr iterator
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define ins insert
#define ers erase
#define lb lower_bound
#define ub upper_bound
#define rnk order_of_key
#define sel find_by_order
#define ctz __builtin_ctz
#define clz __builtin_clz
#define bc __builtin_popcount
#define sz(x) (int((x).size()))
#define all(x) (x).begin(),(x).end()
#define srt(x) sort(all(x))
#define uniq(x) srt(x),(x).erase(unique(all(x)),(x).end())
#define rev(x) reverse(all(x))
#define shf(x) random_shuffle(all(x))
#define nxtp(x) next_permutation(all(x))
//调试相关的宏;
#ifndef DEBUG
#define prt(x) (cerr)
#define asrtWA(s) do if(!(s))exit(0);whl(0)
#define asrtTLE(s) do if(!(s))whl(1);whl(0)
#define asrtMLE(s) do if(!(s))whl(new int);whl(0)
#define asrtOLE(s) do if(!(s))whl(1)puts("OLE");whl(0)
#define asrtRE(s) do if(!(s))*(int*)0=0;whl(0)
#define runtime() (cerr)
#define input(in) freopen(in,"r",stdin)
#define output(out) freopen(out,"w",stdout)
#else
#define prt(x) cerr<<"第"<<__LINE__<<"行\t: "<<#x"\t="<<(x)<
#define asrtWA(s) do if(!(s))cerr<<"assert("#s")"<
#define asrtTLE(s) do if(!(s))cerr<<"assert("#s")"<
#define asrtMLE(s) do if(!(s))cerr<<"assert("#s")"<
#define asrtOLE(s) do if(!(s))cerr<<"assert("#s")"<
#define asrtRE(s) do if(!(s))cerr<<"assert("#s")"<
#define runtime() cerr<<"Used: "<
#define input(in)
#define output(out)
#endif
//常用数据类型;
typedef long long int lli;
typedef double db;
typedef const char* cstr;
typedef string str;
typedef vec<int> vi;
typedef vec vvi;
typedef vec vl;
typedef vec vvl;
typedef vec<bool> vb;
typedef vec vvb;
typedef vec<char> vc;
typedef vec vvc;
typedef vec vs;
typedef pr<int,int> pii;
typedef pr pll;
typedef pr pdd;
typedef vec vpii;
typedef vec vpll;
typedef vec vpdd;
typedef map<int,int> mii;
typedef mapint > msi;
typedef map<char,int> mci;
typedef set<int> si;
typedef set ss;
typedef que<int> qi;
//常用常量:int的最大值;lli的最大值;db的误差相关常数;欧拉常数;圆周率;移动向量;取模使用的除数;
int oo=(~0u)>>1;
lli ooll=(~0ull)>>1;
db inf=1e+10;
db eps=1e-10;
db gam=0.5772156649015328606;
db pi=acos(-1.0);
int dx[]={1,0,-1,0,1,-1,-1,1,0};
int dy[]={0,1,0,-1,1,1,-1,-1,0};
int MOD=1000000007;
//常用函数:最大最小值更新;数学相关函数;输入和输出;树状数组;并查集;可合并堆;
template<typename type>inline bool cmax(type& a,const type& b){rtn atrue :false;}
template<typename type>inline bool cmin(type& a,const type& b){rtn btrue :false;}
template<typename type>inline type sqr(const type& x){rtn x*x;}
template<typename type>inline type mod(const type& x){rtn x%MOD;}
inline int sgn(const db& x){rtn (x>+eps)-(x<-eps);}
inline int dbcmp(const db& a,const db& b){rtn sgn(a-b);}
template<typename type>inline pr operator-(const pr& x){rtn mp(-x.x,-x.y);}
template<typename type>inline pr operator+(const pr& a,const pr& b){rtn mp(a.x+b.x,a.y+b.y);}
template<typename type>inline pr operator-(const pr& a,const pr& b){rtn mp(a.x-b.x,a.y-b.y);}
template<typename type>inline pr operator*(const pr& a,const type& b){rtn mp(a.x*b,a.y*b);}
template<typename type>inline pr operator/(const pr& a,const type& b){rtn mp(a.x/b,a.y/b);}
template<typename type>inline pr& operator-=(pr& a,const pr& b){rtn a=a-b;}
template<typename type>inline pr& operator+=(pr& a,const pr& b){rtn a=a+b;}
template<typename type>inline pr& operator*=(pr& a,const type& b){rtn a=a*b;}
template<typename type>inline pr& operator/=(pr& a,const type& b){rtn a=a/b;}
template<typename type>inline type cross(const pr& a,const pr& b){rtn a.x*b.y-a.y*b.x;}
template<typename type>inline type dot(const pr& a,const pr& b){rtn a.x*b.x+a.y*b.y;}
template<typename type>inline type gcd(type a,type b){if(b)whl((a%=b)&&(b%=a));rtn a+b;}
template<typename type>inline type lcm(type a,type b){rtn a*b/gcd(a,b);}
inline lli bin_pow(lli x,lli y){lli z=1;whl(y){if(y&1)z=mod(z*x);x=mod(sqr(x)),y>>=1;}rtn z;}
template<typename istream,typename first_type,typename second_type>inline istream& operator>>(istream& cin,pr& x){rtn cin>>x.x>>x.y;}
template<typename ostream,typename first_type,typename second_type>inline ostream& operator<<(ostream& cout,const pr& x){rtn cout<" " <template <typename istream,typename type>inline istream& operator>>(istream& cin,vec& x){rep(i,sz(x))cin>>x[i];rtn cin;}
template<typename ostream,typename type>inline ostream& operator<<(ostream& cout,const vec& x){rep(i,sz(x))cout<1 ==sz(x)?"":" ");rtn cout;}
inline ostream& pdb(int prcs,db x){rtn cout<0 );}
template<typename type>inline void bit_inc(vec& st,int x,type inc){whl(x1;}
template<typename type>inline type bit_sum(const vec& st,int x){type s=0;whl(x>=0)s+=st[x],x=(x&(x+1))-1;rtn s;}
template<typename type>inline type bit_kth(const vec& st,int k){int x=0,y=0,z=0;whl((1<<(++y))<=sz(st));rrep(i,y){if((x+=1<sz(st)||z+st[x-1]>k)x-=1<else z+=st[x-1];}rtn x;}
inline void make_set(vi& st){rep(i,sz(st))st[i]=i;}
inline int find_set(vi& st,int x){int y=x,z;whl(y!=st[y])y=st[y];whl(x!=st[x])z=st[x],st[x]=y,x=z;rtn y;}
inline bool union_set(vi& st,int a,int b){a=find_set(st,a),b=find_set(st,b);rtn a!=b?st[a]=b,true:false;}
inline void make_set(vpii& st){rep(i,sz(st))st[i]=mp(i,1);}
inline int find_set(vpii& st,int x){int y=x,z;whl(y!=st[y].x)y=st[y].x;whl(x!=st[x].x)z=st[x].x,st[x].x=y,x=z;rtn y;}
inline bool union_set(vpii& st,int a,int b){a=find_set(st,a),b=find_set(st,b);rtn a!=b?(st[a].y>st[b].y?st[a].x=b,st[a].y+=st[b].y:st[b].x=a,st[b].y+=st[a].y),true:false;}
template<typename type>inline void merge(type& a,type& b){if(sz(a)//初始化;
struct Initializer{
#ifndef DEBUG
Initializer(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
#else
~Initializer(){runtime();}
#endif
}initializer;