zoukankan      html  css  js  c++  java
  • UOJ 2021 NOI Day2 部分题解

    获奖名单

    题目传送门

    Solution

    不难看出,若我们单个 (x)((0,x),(x,0)),两个连 ((x,y),(y,x)) ,除去中间过对称轴的一个两个组,就是找很多个欧拉回路。

    直接来就好了。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 500005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    #define pii pair<int,int>
    #define se second
    #define fi first
    
    int n,m;
    bool vis[MAXN];
    vector <pii> g[MAXN];
    
    int cnt,seq[MAXN];
    void dfs (int u){
    	while (!g[u].empty()){
    		pii it = g[u].back();
    		g[u].pop_back();
    		if (vis[abs(it.se)]) continue;
    		vis[abs (it.se)] = 1,dfs (abs (it.fi)),seq[++ cnt] = it.se;
    	}
    }
    
    signed main(){	
    	read (n,m);
    	for (Int i = 1;i <= n;++ i){
    		int opt,x,y;read (opt,x);
    		if (opt == 1) g[0].push_back ({x,-i}),g[x].push_back ({0,i});
    		else read (y),g[x].push_back ({y,i}),g[y].push_back ({x,-i});    
    	}
    	dfs (0);
    	vector <int> ansl,ansr;
    	for (Int i = 1;i <= cnt;i += 2) ansl.push_back (seq[i]);
    	for (Int i = 2;i <= cnt;i += 2) ansr.push_back (-seq[i]);
    	int mid = 0;
    	for (Int i = 1;i <= m;++ i){
    		sort (g[i].begin(),g[i].end());
    		for (Int j = 0;j < g[i].size();j += 2){
    			if (g[i][j].fi == i && g[i][j].se == -g[i][j + 1].se){
    				mid = abs(g[i][j].se);
    				continue;
    			}
    			if (g[i][j].fi > i || (g[i][j].fi == i && g[i][j].se < 0))
    				ansl.push_back (g[i][j].se),
    				ansr.push_back (-g[i][j + 1].se);  
    		}
    	}  
    	for (Int i = ansl.size() - 1;~i;-- i) write (abs(ansl[i])),putchar (' ');
    	if (mid) write (mid),putchar (' ');
    	for (Int i = 0;i < ansr.size();++ i) write (abs(ansr[i])),putchar (' ');
    	putchar ('
    ');
    	for (Int i = ansl.size() - 1;~i;-- i) write (ansl[i] < 0),putchar (' ');
    	if (mid) write (0),putchar (' ');
    	for (Int i = 0;i < ansr.size();++ i) write (ansr[i] < 0),putchar (' ');
    	putchar ('
    '); 
    	return 0;
    }
    

    诡异操作

    题目传送门

    Solution

    考虑使用线段树维护,对于一个线段树上的区间,我们可以维护 (s_c) 表示二进制位出现次数二进制第 (c) 位为 (1) 的和。你发现这个东西可以进行合并,并且取并操作可以直接对于每一个 (s_c) 并。

    然后对于下取整操作可以直接暴力重构。

    复杂度是个米奇妙妙复杂度,据说是 (Theta(128n+qlog^2n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 300005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    typedef __uint128_t u128;
    inline u128 read() {
        static char buf[100];
        scanf("%s", buf);
        // std::cin >> buf;
        u128 res = 0;
        for(int i = 0;buf[i];++i) {
            res = res << 4 | (buf[i] <= '9' ? buf[i] - '0' : buf[i] - 'a' + 10);
        }
        return res;
    }
    inline void output(u128 res) {
        if(res >= 16)
            output(res / 16);
        putchar(res % 16 >= 10 ? 'a' + res % 16 - 10 : '0' + res % 16);
        //std::cout.put(res % 16 >= 10 ? 'a' + res % 16 - 10 : '0' + res % 16);
    }
    
    #define ll u128
    ll a[MAXN];
    int n,q,len[MAXN << 2];
    
    ll res = ~ll(0);
    struct Segment{
    	ll val[MAXN << 2][20],any[MAXN << 2],laz[MAXN << 2];
    	void pushup (int x){
    		memset (val[x],0,sizeof (u128) * len[x]);
    		int ls = x << 1,rs = x << 1 | 1;
    		val[x][0] = val[ls][0] ^ val[rs][0];ll car = val[ls][0] & val[rs][0];
    		for (Int i = 1;i < len[x];++ i){
    			ll w = val[ls][i] ^ val[rs][i];
    			val[x][i] = w ^ car,car = (car & w) | (val[ls][i] & val[rs][i]);
    		}
    		val[x][len[x]] = car,any[x] = any[x << 1] | any[x << 1 | 1];
    	}
    	ll getv (int x){
    		ll ans = 0;
    		for (Int i = 0;i <= len[x];++ i) ans += val[x][i] << i;
    		return ans;
    	}
    	void pushadd (int x,ll V){
    		for (Int i = 0;i <= len[x];++ i) val[x][i] &= V;
    		laz[x] &= V,any[x] &= V;
    	}
    	void pushdown (int x){pushadd (x << 1,laz[x]),pushadd (x << 1 | 1,laz[x]),laz[x] = res;}
    	void build (int x,int l,int r){
    		laz[x] = res,len[x] = 1;
    		while ((1 << len[x]) <= (r - l + 1)) ++ len[x];
    		if (l == r) return val[x][0] = any[x] = a[l],void ();
    		int mid = l + r >> 1;
    		build (x << 1,l,mid),build (x << 1 | 1,mid + 1,r);
    		pushup (x);
    	}
    	void modify1 (int x,int l,int r,int ql,int qr,ll V){
    		if (l >= ql && r <= qr) return pushadd (x,V),void ();
    		int mid = l + r >> 1;pushdown (x);
    		if (ql <= mid) modify1 (x << 1,l,mid,ql,qr,V);
    		if (qr > mid) modify1 (x << 1 | 1,mid + 1,r,ql,qr,V);
    		pushup (x); 
    	}
    	void div (int x,int l,int r,ll V){
    		if (!any[x]) return ;
    		if (l == r) return any[x] = (val[x][0] /= V),void ();
    		int mid = l + r >> 1;pushdown (x);
    		div (x << 1,l,mid,V),div (x << 1 | 1,mid + 1,r,V);
    		pushup (x);
    	}
    	ll query (int x,int l,int r,int ql,int qr){
    		if (l >= ql && r <= qr) return getv (x);
    		int mid = l + r >> 1;pushdown (x);ll res = 0;
    		if (ql <= mid) res += query (x << 1,l,mid,ql,qr);
    		if (qr > mid) res += query (x << 1 | 1,mid + 1,r,ql,qr);
    		return res; 
    	}
    	void modify2 (int x,int l,int r,int ql,int qr,ll V){
    		if (l >= ql && r <= qr) return div (x,l,r,V);
    		int mid = l + r >> 1;pushdown (x);
    		if (ql <= mid) modify2 (x << 1,l,mid,ql,qr,V);
    		if (qr > mid) modify2 (x << 1 | 1,mid + 1,r,ql,qr,V);
    		pushup (x);
    	}
    }T;
    
    signed main(){	
    	read (n,q);
    	for (Int i = 1;i <= n;++ i) a[i] = read ();
    	T.build (1,1,n);
    	while (q --> 0){
    		int opt,qL,qR;ll V;
    		read (opt,qL,qR);
    		if (opt <= 2){
    			V = read ();
    			if (opt == 1 && V > 1) T.modify2 (1,1,n,qL,qR,V);
    			else if (opt == 2) T.modify1 (1,1,n,qL,qR,V);  
    		}
    		else output (T.query (1,1,n,qL,qR)),putchar ('
    ');
    	} 
    	return 0;
    }
    
    
  • 相关阅读:
    jquery 中 $.map 的使用方法
    数据库 'MessageManage' 的事务日志已满。若要查明无法重用日志中的空间的原因,请参阅 sys.databases 中的 log_reuse_wait_desc 列。
    Post提交
    MD5加密、时间戳转换、base64算法加密、解密
    C#中timer类的用法
    软件项目版本号的命名规则及格式
    SQL Server数据库脚本备份与还原
    C# Out,Ref 学习总结
    在线工具
    构造和析构 的顺序
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/15036324.html
Copyright © 2011-2022 走看看