[考試總結]noip模擬27
這個牛半仙可真的是人生贏家
這波中二的名字又是讓我心頭一震,然後有發現沒有 \(PDF\) 和大樣例。
沒有大樣例就意味著不能打掛一處。
然而這是讓我最頭疼的事情。。。
\(100\) 多行的程式碼一般對我來說也就是不到 \(5\) 分鐘就能打完,然後開始 \(50min\) 除錯。。。
有億點虧。。。
其實這樣的聯賽模擬題目使勁想一想還是可以想出正解的,然而腦袋裡不知道為什麼總是想要去打一個暴力。。。
確實該改一改這個毛病。
牛半仙的妹子圖
一開始看這個題目的時候就覺得這個出題人真的是中二至極。
這就是我打掛這個題目的理由
這個題目實際上很像奶牛跨欄那個題目,就是要求到達一個點路徑上的最小值的最大。
然而當時所有人似乎用的都是 \(floyed\) 高階演算法。。。
然後這個題目就不知道用 \(dij\) 咋搞。。。
其實也差不多,我想的是可以把所有邊壓進 ¥priority_queue$ 當中,這樣的話也能維護這個。
然而因為不是很經常使用 \(dijkstra\) 和 \(priority_queue\),所以。。。
我壓根不知道該 反著過載。
所以我是這麼寫的。。。
class xin_data { private: friend bool operator < (xin_data x,xin_data y) {return x.w < y.w;} public: int w,pos; };
然後就 \(gg\) 了。
因為 \(w\leq600\) ,所以可以建立 權值陣列。
然後就能跑了。
#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 int long long namespace xin_io { #define scanf nb = scanf #define debug cout<<"debug"<<endl #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++ char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull; void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);} inline int get() { register int s = 0,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 s * f; } template<typename type>inline void write(type x,char out) { if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x; register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10; throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void(); } } using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; static const ll llinf = 1e17+7; namespace xin { class xin_edge{public:int next,ver,w;}edge[maxn]; int head[maxn],zhi = 0; inline void add(int x,int y,int z) {edge[++zhi].ver = y;edge[zhi].w = z; edge[zhi].next = head[x]; head[x] = zhi;} class xin_data { private: friend bool operator < (xin_data x,xin_data y) {return x.val > y.val;} public: int val,pos; xin_data(){} xin_data(int val,int pos):val(val),pos(pos){} }; std::priority_queue<xin_data>q; int n,m,qnum,st,op,mod,c[maxn],dis[maxn]; int ton[maxn],sum = 0; int he[maxn],base[maxn],cnt,num[maxn]; bool vis[maxn]; inline short main() { #ifndef ONLINE_JUDGE openfile(); #endif n = get(); m = get(); qnum = get(); st = get(); op = get(); if(op) mod = get(); try(i,1,n) c[i] = get(); try(i,1,m) { register int x = get(),y = get(),z = get(); add(x,y,z); add(y,x,z); } ton[c[st]]++; sum ++; for(register int i=head[st];i;i=edge[i].next) q.push(xin_data(edge[i].w,edge[i].ver)); int maxx = 0; base[++cnt] = 1; num[cnt] = sum; while(!q.empty()) { register int dis = q.top().val,now = q.top().pos;q.pop(); if(vis[now])continue; vis[now] = 1; maxx = std::max(maxx,dis); ton[c[now]]++; if(ton[c[now]] == 1) {sum++; if(base[cnt] xor maxx) base[++cnt] = maxx; num[cnt] = sum;} for(register int i=head[now];i;i=edge[i].next) q.push(xin_data(edge[i].w,edge[i].ver)); } base[++cnt] = inf; try(i,1,cnt) he[i] = he[i-1] + num[i - 1] * (base[i] - base[i-1]); int pre = 0; try(i,1,qnum) { register int l = get(),r = get(); if(op) l = (l xor pre) % mod + 1,r = (r xor pre) % mod + 1; if(r < l) std::swap(l,r); register int lb = std::upper_bound(base+1,base+cnt+1,l) - base,rb = std::upper_bound(base+1,base+cnt+1,r) - base - 1; register int ans = he[rb] - he[lb]; ans += (base[lb] - l) * num[lb - 1]; ans += (r - base[rb] + 1) * num[rb]; write(pre = ans,'\n'); } return 0; } } signed main(){return xin::main();}
牛半仙的妹子Tree
這個題目說實話我是真的沒有想到暴力直接可過的。
然後加強資料之後。。。還是能過。。。
其實就是記錄下來每一個 \(1\) 操作。
然後在每一個 \(3\) 操作的時候遍歷整個 \(1\) 操作的陣列。
然後而操作就是把那個陣列的指標清零就行了。
然而 \(lca\) 一定要 \(\mathcal O(1)\) 求,不然一定會 \(T\)。
#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)
namespace xin_io
{
#define scanf nb = scanf
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
inline int get()
{
register int s = 0,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 s * f;
}
template<typename type>inline void write(type x,char out)
{
if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10;
throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; static const ll llinf = 1e17+7;
namespace xin
{
class xin_edge{public:int next,ver;} edge[maxn];
int head[maxn],cnt = 0;
inline void add(int x,int y){edge[++cnt].ver = y; edge[cnt].next = head[x]; head[x] = cnt;}
int dep[maxn],f[maxn][32],lg[maxn],fr[maxn],num;
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1;
f[++num][0] = x;
if(!fr[x])fr[x]=num;
for(int i=head[x];i;i=edge[i].next)
{
int dd=edge[i].ver;
if(dd==fa)continue;
dfs(dd,x);
f[++num][0]=x;
if(!fr[x])fr[x]=num;
}
}
void RMQ()
{
for(register int j=1;(1<<j)<=num;++j)
for(register int i=1;i+(1<<j)-1<=num;++i)
if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]])f[i][j]=f[i][j-1];
else f[i][j]=f[i+(1<<(j-1))][j-1];
try(i,2,num) lg[i] = lg[i>>1] + 1;
}
int lca(int x,int y)
{
x = fr[x]; y = fr[y];
if(x > y) x ^= y ^= x ^= y;
int len=lg[y-x+1];
return dep[f[x][len]]<dep[f[y-(1<<len)+1][len]]?f[x][len]:f[y-(1<<len)+1][len];
}
inline int distance(int x,int y){return dep[x] + dep[y] - 2 * dep[lca(x,y)];}
int a[maxn],temp[maxn],zhi = 0;
int n,m;
bool cold[maxn];
void kuosan()
{
try(i,1,zhi) temp[i] = a[i];
int ms = zhi; zhi = 0;
try(i,1,ms)
{
register int x = temp[i];
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver;
if(!cold[y]) cold[y] = 1,a[++zhi] = y;
}
}
}
class xin_data
{
public:
int tim,pos;
xin_data(){}
xin_data(int tim,int pos):tim(tim),pos(pos){}
}d[maxn];
bool sp1 = 1,sp2 = 1;
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get(); m = get();
try(i,1,n-1)
{
register int x = get(),y = get();
add(x,y); add(y,x);
if(x xor 1) sp1 = 0;
if((x xor i) or (y xor (i + 1))) sp2 = 0;
}
if(sp1)
{
int tim = 0,cnt = 0;
try(i,1,m)
{
register int op = get(),x = get();
if(cnt)
{
if(cold[1]) cnt = n;
else cold[1] = 1;
}
if(op == 1)
{
cold[x] = 1;
cnt++;
}
if(op == 2)
{
cnt = 0;
memset(cold,0,sizeof(bool) * (n + 1));
}
if(op == 3)
{
if(cnt == n) printf("wrxcsd\n");
else printf(cold[x] ? "wrxcsd\n" : "orzFsYo\n");
}
}
return 0;
}
if(sp2)
{
try(i,1,m)
{
register int op = get(),x = get();
kuosan();
if(op == 1)
{
a[++zhi] = x;
cold[x] = true;
}
if(op == 2)
{
memset(cold,0,sizeof(bool) * (n + 1));
zhi = 0;
}
if(op == 3)
printf(cold[x] ? "wrxcsd\n" : "orzFsYo\n");
}
return 0;
}
dfs(1,0); RMQ();
try(tim,1,m)
{
register int op = get(),x = get();
if(op == 1)
{
d[++zhi] = xin_data(tim,x);
}
if(op == 2)
{
zhi = 0;
}
if(op == 3)
{
bool ok = 1;
try(i,1,zhi)
{
register int ks = tim - d[i].tim,dis = distance(x,d[i].pos);
if(ks >= dis) {ok = 0;break;}
}
puts(ok ? "orzFsYo" : "wrxcsd");
}
}
return 0;
}
}
signed main(){return xin::main();}
牛半仙的妹子序列
似乎是極長上升子序列的板子。
然而我不會。。。
然後 \(gg\) 了,直接這個題目抱 \(\color{red}{0}\) 了。
用線段樹維護這個玩意,似乎和昨天的第二題有些相似。
#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)
namespace xin_io
{
#define scanf nb = scanf
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
inline int get()
{
register int s = 0,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 s * f;
}
template<typename type>inline void write(type x,char out)
{
if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10;
throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; static const ll llinf = 1e17+7;
namespace xin
{
int n;
int c[maxn],pos[maxn];
int f[maxn],maxx;
class xin_segment
{
private:
#define ls(fa) (fa << 1)
#define rs(fa) (fa << 1 | 1)
int lim(int fa,int val)
{
if(t[fa].tag) return t[fa].s > val ? f[t[fa].s] : 0;
return t[rs(fa)].s < val ? lim(ls(fa),val) : (t[fa].lans + lim(rs(fa),val)) % mod;
}
inline void up(int fa)
{
t[fa].s = std::max(t[ls(fa)].s,t[rs(fa)].s);
t[fa].lans = lim(ls(fa),t[rs(fa)].s);
}
public:
class xin_tree{public:int s,lans,tag;}t[maxn];
void build(int fa,int l,int r)
{
if(l == r) return t[fa].tag = 1,void(); //tag the leave point
register int mid = l + r >> 1;
build(ls(fa),l,mid); build(rs(fa),mid+1,r);
}
void modify(int fa,int l,int r,int pos,int val)
{
if(pos > r or pos < l) return;
if(l == r) return t[fa].s = val,void();
register int mid = l + r >> 1;
modify(ls(fa),l,mid,pos,val); modify(rs(fa),mid+1,r,pos,val);
up(fa);
}
int query(int fa,int l,int r,int ql,int qr)
{
if(ql > r or qr < l) return 0;
if(ql <= l and qr >= r)
{
register int temp = maxx; maxx = std::max(maxx,t[fa].s);
return lim(fa,temp);
}
register int mid = l + r >> 1,res = 0;
res = (res + query(rs(fa),mid+1,r,ql,qr)) % mod; res = (res + query(ls(fa),l,mid,ql,qr)) % mod;
return res;
}
}t;
class xin_bit
{
private:
#define lowbit(x) (x & -x)
public:
int s[maxn];
inline void add(int x,int val)
{for(register int i=x;i<=n;i+=lowbit(i)) s[i] += val;}
inline int ask(int x)
{int res = 0;for(register int i=x;i;i-=lowbit(i)) res += s[i];return res;}
}bit;
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get(); try(i,1,n) c[i] = get(),pos[c[i]] = i;
t.build(1,1,n);
try(i,1,n)
{
register int x = pos[i]; maxx = 0;
f[i] = t.query(1,1,n,1,x);
if(!f[i]) f[i] = 1;
t.modify(1,1,n,x,i);
}
int ans = 0;
throw(i,n,1)
{
if(bit.ask(n) == bit.ask(pos[i])) ans = (ans + f[i]) % mod;
bit.add(pos[i],1);
}
cout<<ans<<endl;
return 0;
}
}
signed main(){return xin::main();}