1.2588: Spoj 10628. Count on a tree
树上不修改第k大。
迷之RE的原因是被精妙地炸掉了intQAQ
然后又PE
然后才A
我想知道bzoj的人是不是蛇精病。。。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
#define RepG(i,x) for(int i = head[x];~ i;i = edge[i].next)
#define v edge[i].to
#define u t[x]
#define o t[y]
#define e t[z]
#define s t[p]
#define mid ((long long)l + r >> 1)
#define lson u.lc,l,mid,o.lc
#define rson u.rc,mid + 1,r,o.rc
using namespace std;
const int N = 100005;
const int inf = (1ll << 31) - 5;
struct Tree{int lc,rc,cnt;}t[N * 40];
struct Edge{int next,to;}edge[N << 1];
int top[N],rt[N],dep[N],fa[N],sz[N],n,m,a[N],cnt,head[N],val,son[N],tot;
void save(int a,int b){edge[cnt] = (Edge){head[a],b},head[a] = cnt ++;}
void dfs(int x){sz[x] = 1;RepG(i,x)if(v != fa[x]){fa[v] = x,dep[v] = dep[x] + 1,dfs(v),sz[x] += sz[v];if(sz[v] > sz[son[x]])son[x] = v;}}
void dfs(int x,int tp){top[x] = tp;if(son[x])dfs(son[x],tp);RepG(i,x)if(v != fa[x] && v != son[x])dfs(v,v);}
void Ins(int &x,int l,int r,int y){x = ++ tot;u = o;u.cnt ++;if(l == r)return;val <= mid ? Ins(lson) : Ins(rson);}
void ReBuild(int x){val = a[x];Ins(rt[x],0,inf,rt[fa[x]]);RepG(i,x)if(v != fa[x])ReBuild(v);}
int lca(int x,int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])swap(x,y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
int Qry(int x,int l,int r,int y,int z,int p,int k)
{
if(l == r)return l;
int res = t[u.lc].cnt + t[o.lc].cnt - t[e.lc].cnt - t[s.lc].cnt;
if(res >= k)return Qry(lson,e.lc,s.lc,k);
else return Qry(rson,e.rc,s.rc,k - res);
}
int main ()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
Rep(i,n)scanf("%d",&a[i]);
Rep(i,n - 1){int x,y;scanf("%d%d",&x,&y);save(x,y),save(y,x);}
int ls = 0;
dfs(1),dfs(1,1);
ReBuild(1);
Rep(i,m)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
x ^= ls;
int z = lca(x,y),p = fa[z];
printf("%d",ls = Qry(rt[x],0,inf,rt[y],rt[z],rt[p],k));
if (i != m) puts ("");
}
return 0;
}
2.2326: [HNOI2011]数学作业
显然的递推式是:
f[i]=f[i−1]∗10kmodM+imodM
然后我上节课学习了矩阵乘法,刚好来应用一下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
using namespace std;
long long n;
int M;
struct Matrix{long long a[5][5];};
Matrix Init(){Matrix k;memset(k.a,0,sizeof(k.a));return k;}
Matrix operator*(Matrix x,Matrix y)
{
Matrix c = Init();
Rep(i,3)Rep(k,3)Rep(j,3)c.a[i][j] = (c.a[i][j] + ((x.a[i][k] % M) * (y.a[k][j] % M)) % M) % M;
return c;
}
void print(Matrix c)
{
Rep(i,3){Rep(j,3)printf("%lld ",c.a[i][j]);puts("");}
}
Matrix FP(Matrix w,long long p)
{
//print(w);
//printf("%lld\n",p);
Matrix c = Init();
Rep(i,3)c.a[i][i] = 1;
while(p)
{
if(p & 1)c = c * w;
p >>= 1;
w = w * w;
}
return c;
}
int main ()
{
scanf("%lld%d",&n,&M);
Matrix c,ans;
c = Init(),ans = Init();
c.a[1][2] = 1,c.a[1][3] = 1,c.a[2][2] = 1,c.a[2][3] = 1,c.a[3][3] = 1;
ans.a[3][1] = 1;
for(long long i = 1,k = 1;i <= n;i *= 10,k ++)
{
long long j = min(i * 10 - 1,n);
c.a[1][1] = (long long)pow(10,k);c.a[1][2] = c.a[1][3] = c.a[2][3] = c.a[2][2] = c.a[3][3] = 1;
c = FP(c,j - i + 1);
ans = c * ans;
}
printf("%lld\n",ans.a[1][1]);
return 0;
}
3.虽然是奶牛题然而感觉还是很可做
(至少感觉思路很好)
Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司支付一定的费用。 FJ的农场周围分布着 N(1<=N<=1,000)根按1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共 P(1<=P<=10,000) 对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。 第i对电话线杆的两个端点分别为 Ai、Bi ,它们间的距离为 Li(1<=Li<=1,000,000) 。数据中保证每对 Ai,Bi 最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为N的电话线杆上。也就是说,FJ的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。 经过谈判,电信公司最终同意免费为FJ连结 K(0<=K<N) 对由FJ指定的电话线杆。对于此外的那些电话线,FJ需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过 K 对,那么FJ的总支出为0。 请你计算一下,FJ最少需要在电话线上花多少钱。
题解:思路很明确是二分答案,然后问题是之后怎么办。
之后显然是把>W的那些边都变成1,其余变为0跑一下最短路就成了。
这个题的思路其实很像HeoiD1T2我会说。。。?
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
#define v edge[i].to
#define RepG(i,x) for(int i = head[x];~ i;i = edge[i].next)
using namespace std;
const int N = 1005;
struct Edge{int next,to,w;}edge[N * 20];
int n,m,K,dis[N],head[N],q[N * 40],cnt;bool vis[N];
void save(int a,int b,int c){edge[cnt] = (Edge){head[a],b,c},head[a] = cnt ++;}
bool spfa(int ans)
{
memset(dis,127,sizeof(dis));
int h,t;
dis[1] = 0;h = 0,t = 1,q[0] = 1;vis[1] = 1;
while(h != t)
{
int x = q[h ++];
if(h == 1024)h = 0 ;
RepG(i,x)
if(dis[v] > dis[x] + (bool)(edge[i].w > ans))
{
dis[v] = dis[x] + (bool)(edge[i].w > ans);
if(!vis[v])q[t ++] = v,vis[v] = 1;
if(t == 1024)t = 0;
}
vis[x] = 0;
}
return dis[n] <= K;
}
int main ()
{
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&K);
Rep(i,m)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
save(a,b,c),save(b,a,c);
}
int l = 0,r = 1000001,ans = -1;
while(l <= r)
{
int mid = l + r >> 1;
if(spfa(mid))ans = mid,r = mid - 1;
else l = mid + 1;
}
printf("%d",ans);
return 0;
}
4.每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛棚”.牛棚i的后继牛棚是Xi.他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去,就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果. 第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.
窝看到第一眼的时候:
SB题,一眼秒。
然后就WA了。。。
然而大体思路是对的只不过自己智障写挂了QAQ
首先缩点并且重建整个图,考虑到在一个scc上的点可以获得它的所有后继的答案,那么我们记忆化搜索一发即可。
然后就没有了QAQ
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Rep(i,n) for(int i = 1;i <= n;i ++)
#define RepG(i,x) for(int i = head[x];~ i;i = edge[i].next)
using namespace std;
const int N = 100005;
int to[N],n,cnt,head[N],dfn[N],stk[N],tp,low[N],dsz,scc,bel[N],sz[N];
bool vis[N],del[N];
struct Edge{int next,to;}edge[N];
void save(int a,int b){edge[cnt] = (Edge){head[a],b},head[a] = cnt ++;}
void dfs(int x)
{
dfn[stk[++ tp] = x] = low[x] = ++ dsz;int y;
int v = to[x];
if(!dfn[v])dfs(v),low[x] = min(low[v],low[x]);
else if(!del[v])low[x] = min(dfn[v],low[x]);
if(dfn[x] == low[x]){++ scc;do{bel[y = stk[tp --]] = scc,sz[scc] ++;del[y] = 1;}while(y != x);}
}
#define v edge[i].to
int ans[N];
void ReBuild(){Rep(i,n)if(bel[i] != bel[to[i]])save(bel[i],bel[to[i]]);}
int ReDfs(int x)
{
if(ans[x])return ans[x];
ans[x] = sz[x];
RepG(i,x)ans[x] += ReDfs(v);
return ans[x];
}
int main ()
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
Rep(i,n)scanf("%d",&to[i]);
Rep(i,n)if(!dfn[i])dfs(i);
ReBuild();
Rep(i,n)printf("%d\n",ReDfs(bel[i]));
return 0;
}
剩下A的几道题都是窝东拼西凑凑出的水题QAQ
哦其实我上面几道题也是水题QAQ
真是颓废的一天QAQ